기본 콘텐츠로 건너뛰기

[WinForm] BackgroundWorker...

프로젝트에서 어떤 파일을 복사하거나, 어떤 업무 처리를 연속적으로 처리하거나, 또는 다른 서버로 정보를 전달하여야 하는 경우와 같이 시간이 소비되는 작업에서는 사용자에게 작업의 단계별 진행을 알려주어야 하는 경우가 많다.

보통은 UI Thread에서 대 부분의 작업을 진행하므로 별다른 문제가 없지만, 작업이 길고, 다량의 작업이 된다면 Thread가 먹통(?)이 되기 때문에 ProgressBar 에 진척 사항이 보여질 수가 없다. 즉 작업을 동기적으로 처리하게되면 Wait 상태가 되기 때문이다.

이런 경우는 대상 작업을 별도의 Thread로 분리해서 운영을 하여야 한다. 즉, UI Thread 가 Busy 상태로 빠지지 않게 하는 것이다.

이런 작업을 위한 부분이 아래와 같이 BackgroundWorker를 이용하는 것이다. (물론 Thread를 생성해서 처리를 해도 된다.)

다음은 대략적인 개념을 알 수 있는 샘플이다.

public partial class Form1 : Form {
#region Fields

private BackgroundWorker worker;

#endregion

#region Constructors

public Form1() {
InitializeComponent();
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
// 실제 작업 메서드 연결
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
// 진행 상황 처리 메서드 연결
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
// 작업 완료 처리 메서드 연결
worker.RunWorkerCompleted += 
                    new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
}

#endregion
   
#region Event Handlers
   
// Worker Thread가 실제 하는 일
void worker_DoWork(object sender, DoWorkEventArgs e) {
// 실제 처리 작업
foreach(....) {
...
// 진행상황 처리
worker.ReportProgress(percent);
}
}

// Progress 진행 상황 
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) {
this.progressBar1.Value = e.ProgressPercentage;            
}

// 작업 완료
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
// 에러 검증
if (e.Error != null) {
lblMsg.Text = e.Error.Message;
MessageBox.Show(e.Error.Message, "Error");          
return;
}

lblMsg.Text = "완료되었습니다";
}      

private void btnRun_Click(object sender, EventArgs e) {
worker.RunWorkerAsync(); // 비동기(Async)로 실행 
}
   
#endregion
}

가장 중요한 부분은 UI Thread 와 분리해서 비 동기 처리 (BackgroundWorder or Thread) 를 해야 한다는 점이다.

댓글