Common Tip/장애 경험치2009. 3. 12. 15:20

http://www.devpia.com/Maeul/Contents/Detail.aspx?BoardID=17&MAEULNo=8&no=106756&ref=106756
http://blog.naver.com/hanbyi?Redirect=Log&logNo=110012603567 <-- 이거 공부하자

타이머 말고,
BackgroundWorker 라는 클래스를 사용하여 문제를 해결할 수 있습니다.
BackgroundWorker 클래스는 말그래도 메인 UI 쓰레드가 아닌 다른 쓰레드에서 작업을 처리할 수 있도록
도와주는 .NET 클래스입니다.
이 클래스를 사용하면 복잡한 쓰레드 문제를 피할 수 있으며 원하는 결과를 쉽게 얻을 수 있습니다.
방법은 다음과 같습니다.

메인 UI 쓰레드가 아닌 다른 쓰레드에서 폼의 레이블 컨트롤을 매 초마다 업데이트 하도록 하는 겁니다.
BackgroundWorker 클래스에 대해 잠시 설명하자면..
 BackgroundWorker 클래스의 인스턴스를 생성한 다음,
이 인스턴스의 RunWorkerAsync() 메소드를 실행하면,
백그라운드 작업이 진행됩니다. 이 때, DoWork 이벤트가 일어나게 됩니다.

 즉, DoWork 이벤트에 적절한 이벤트를 핸들러를 추가하면, 이 이벤트 핸들러가
RunWorkerAsync() 메소드 실행시에 다른 쓰레드에서 실행된다는 뜻입니다.

 실질적인 백그라운드 작업 코드를 DoWork 이벤트 핸들러에 추가하면 되겠습니다.
DoWork 이벤트 핸들러가 백그라운드 작업을 진행하는 동안에,중간 중간 정보를 반환받아야 한다면,
(이번 문제처럼 중간 중간 레이블 컨트롤을 업데이트 한다는 것처럼)

 DoWork 이벤트 핸들러 안에서, ReportProgress() 메소드를 호출해야 합니다.
이 메소드가 호출되면,  ProgressChanged 이벤트가 일어나는데, 
이 이벤트에 대한 이벤트 핸들러에 레이블 컨트롤을 업데이트 하는 논리를 추가하면 되겠습니다.
마지막으로 DoWork 이벤트 핸들러의 모든 작업이 끝나면, RunWorkerCompleted 이벤트가 일어납니다.

이 이벤트에 대한 이벤트 핸들러에서 최종 마무리 작업을 수행하면 되겠습니다.
이러한 절차를 잘 염두에 두면, 매우 쉬운 백그라운드 작업 코드를 작성할 수 있답니다.

 다음과 같은 코드를 살펴 보죠.

 public partial class Form1 : Form
{
        private BackgroundWorker myWorker = new BackgroundWorker(); 

        public Form1()
        {
            InitializeComponent(); 

            myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
            myWorker.WorkerReportsProgress = true;
            myWorker.ProgressChanged += new ProgressChangedEventHandler(myWorker_ProgressChanged);
            myWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(myWorker_RunWorkerCompleted);
        }

        void myWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; i <= 5; ++i)
            {
                Thread.Sleep(1000);
                myWorker.ReportProgress(i);
            }

            Thread.Sleep(1000);
        }

        void myWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.label1.Text = "No. " + e.ProgressPercentage.ToString();
        }

        void myWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.label1.Text = "Completed!";
        }
        private void button1_Click(object sender, EventArgs e)
        {
            if (myWorker.IsBusy != true)
            myWorker.RunWorkerAsync();
        }
 }

Posted by penguindori