BackgroundWorker 클래스
BackgroundWorker클래스는 별도의 쓰레드에게 어떤 일을 시키기 위해 사용하는 클래스이다. 흔히 백그라운 쓰레드 혹은 워커 쓰레스라 불리우는 별도의 쓰레드에서는 UI Thread와 별도로 어떤 작업을 수행하는데 사용된다. BackgroundWorker로부터 생성된 객체는 DoWork이벤트 핸들러를 통해 실제 작업할 내용을 지정하고, ProgressChanged이벤트를 통해 진척 사항을 전달하며, RunWorkerCompleted 이벤트를 통해 완료 후 실행될 작업을 지정한다. DoWork 이벤트 핸들러는 Worker Thread에서 돌고, ProgressChanged와 RunWorkerCompleted 이벤트 핸들러는 UI Thread에서 돈다. BackgroundWorker클래스 객체는 Thread클래스와 같이 쓰레드를 직접 생성하는 것이 아니라, Thread Pool로부터 가져온 쓰레드를 사용한다.
//Thread객체 생성
BackgroundWorker worker = new BackgroundWorker();
// 이벤트 핸들러 지정
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
// 실행
worker.RunWorkerAsync();
BackgroundWorker worker = new BackgroundWorker();
// 이벤트 핸들러 지정
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
// 실행
worker.RunWorkerAsync();
BackgroundWorker 사용 예제
아래 예제는 BackgroundWorker를 통해 파일 복사를 비동기적으로 수행하는 것으로 파일이 복사되는 진행 사항이 ProgressBar 컨트롤을 통해 보여진다. 많은 파일복사가 일어날 경우, 비동기(Asynchronous) 처리를 하지 않으면, UI Thread가 너무 바빠져 UI가 먹통인 경우가 발생할 수 있다.
예제
public partial class Form1 : Form
{
private BackgroundWorker worker;
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);
}
// Worker Thread가 실제 하는 일
void worker_DoWork(object sender, DoWorkEventArgs e)
{
string srcDir = @"C:\Temp\_Src";
string destDir = @"C:\Temp\_Dest";
DirectoryInfo di = new DirectoryInfo(srcDir);
FileInfo[] fileInfos = di.GetFiles();
int totalFiles = fileInfos.Length;
int counter = 0;
int pct = 0;
foreach (var fi in fileInfos)
{
string destFile = Path.Combine(destDir, fi.Name);
File.Copy(fi.FullName, destFile);
pct = ((++counter * 100) / totalFiles);
worker.ReportProgress(pct);
}
}
// Progress 리포트 - UI Thread
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage;
}
// 작업 완료 - UI Thread
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)
{
// 비동기(Async)로 실행
worker.RunWorkerAsync();
}
}
{
private BackgroundWorker worker;
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);
}
// Worker Thread가 실제 하는 일
void worker_DoWork(object sender, DoWorkEventArgs e)
{
string srcDir = @"C:\Temp\_Src";
string destDir = @"C:\Temp\_Dest";
DirectoryInfo di = new DirectoryInfo(srcDir);
FileInfo[] fileInfos = di.GetFiles();
int totalFiles = fileInfos.Length;
int counter = 0;
int pct = 0;
foreach (var fi in fileInfos)
{
string destFile = Path.Combine(destDir, fi.Name);
File.Copy(fi.FullName, destFile);
pct = ((++counter * 100) / totalFiles);
worker.ReportProgress(pct);
}
}
// Progress 리포트 - UI Thread
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage;
}
// 작업 완료 - UI Thread
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)
{
// 비동기(Async)로 실행
worker.RunWorkerAsync();
}
}