BackgroundWorker 클래스를 이용한 비동기 작업 샘플 코드입니다.
MDSN 의 셈플이 더 좋습니다. 더 좋은 샘플은 MSDN을 참조하세요. [링크]
샘플입니다. :)
1: // Form1.cs
2: using System;
3: using System.Collections.Generic;
4: using System.ComponentModel;
5: using System.Data;
6: using System.Drawing;
7: using System.Linq;
8: using System.Text;
9: using System.Windows.Forms;
10:
11: namespace DemoProgressBar
12: {
13: public partial class Form1 : Form
14: {
15: public Form1()
16: {
17: InitializeComponent();
18: this.Load += new EventHandler(Form1_Load);
19: this.btnStart.Click += new EventHandler(button1_Click);
20: this.btnCancel.Click += new EventHandler(button2_Click);
21:
22: // BackgroundWorker
23: this.bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
24: this.bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
25: this.bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
26: }
27:
28: private void Form1_Load(object sender, EventArgs e)
29: {
30: try
31: {
32: // 작업 취소를 사용
33: this.bgWorker.WorkerSupportsCancellation = true;
34:
35: // 작업 진행률 업데이트 보고를 사용
36: this.bgWorker.WorkerReportsProgress = true;
37:
38: this.btnStart.Enabled = true;
39: this.btnCancel.Enabled = false;
40:
41: this.lblWorkCount.Text = "0";
42: }
43: catch (Exception ex)
44: {
45: throw new Exception("오류가 발생했습니다", ex);
46: }
47: }
48:
49: #region 메서드
50:
51: /// <summary>
52: /// 처리할 작업입니다.
53: /// </summary>
54: private void DoWork(BackgroundWorker worker, DoWorkEventArgs e)
55: {
56: /*
57: * 실행중인 Form 과 다른 쓰레드에서 동작하므로
58: * 처리할 메서드에서는 UI 객체의 속성값(Value, Text 등..)을 사용하지 못합니다.
59: *
60: * 작업에 필요한 값은 매개변수로 전달받아야 하고 UI객체의 상태를 변화시킬 필요가 있는 경우
61: * ProgressChanged
62: * RunWorkerCompleted
63: * 이벤트를 사용해야 합니다.
64: *
65: */
66:
67: double nMax = 1000.0;
68: int nExe = 0;
69:
70: while (nMax > nExe)
71: {
72: // 작업이 취소 요청이 되었는지 검사
73: if (worker.CancellationPending)
74: {
75: e.Cancel = true;
76: break;
77: }
78: else
79: {
80: System.Threading.Thread.Sleep(200);
81: nExe++;
82:
83: // 진행률 업데이트하기 위해 ProgressChanged 이벤트를 발생시킵니다.
84: worker.ReportProgress((int)((nExe / nMax) * 100));
85: }
86: }
87: }
88:
89: #endregion
90:
91: #region 이벤트 핸들러
92:
93: /// <summary>
94: /// 시작버튼 클릭
95: /// </summary>
96: private void button1_Click(object sender, EventArgs e)
97: {
98: try
99: {
100: this.progressBar.Value = 0;
101: this.progressBar.Maximum = 100;
102: this.progressBar.Step = 1;
103:
104: this.lblWorkCount.Text = "0";
105:
106: this.btnStart.Enabled = false;
107: this.btnCancel.Enabled = true;
108:
109: this.Cursor = Cursors.WaitCursor;
110:
111: // 비동기로 작업을 시작합니다. DoWork 이벤트를 발생
112: this.bgWorker.RunWorkerAsync(null);
113: }
114: catch (Exception ex)
115: {
116: throw new Exception("오류가 발생했습니다", ex);
117: }
118: }
119:
120: /// <summary>
121: /// 취소 버튼 클릭
122: /// </summary>
123: private void button2_Click(object sender, EventArgs e)
124: {
125: try
126: {
127: // 작업 취소요청
128: this.bgWorker.CancelAsync();
129: }
130: catch (Exception ex)
131: {
132: throw new Exception("오류가 발생했습니다", ex);
133: }
134: }
135:
136: /// <summary>
137: /// 작업을 시작
138: /// </summary>
139: private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
140: {
141: try
142: {
143: this.DoWork((BackgroundWorker)sender, e);
144: e.Result = null;
145: }
146: catch (Exception ex)
147: {
148: throw new Exception("오류가 발생했습니다", ex);
149: }
150: }
151:
152: /// <summary>
153: /// 작업 진행률을 업데이트
154: /// </summary>
155: private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
156: {
157: try
158: {
159: this.progressBar.Value = e.ProgressPercentage;
160: int nTmp = 0;
161: int.TryParse(this.lblWorkCount.Text, out nTmp);
162: nTmp++;
163: this.lblWorkCount.Text = nTmp.ToString();
164:
165: }
166: catch (Exception ex)
167: {
168: throw new Exception("오류가 발생했습니다", ex);
169: }
170: }
171:
172: /// <summary>
173: /// 작업이 완료상태(예외, 취소, 완료)가 되면 발생하는 이벤트입니다
174: /// </summary>
175: /// <param name="sender"></param>
176: /// <param name="e"></param>
177: private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
178: {
179: try
180: {
181: if (e.Error != null) // 예외 발생
182: {
183: MessageBox.Show(string.Format("{0}\r\n{1}", "오류가 발생했습니다.", e.Error.Message));
184: }
185: else if (e.Cancelled) // 작업취소
186: {
187: MessageBox.Show("취소되었습니다");
188: }
189: else // 완료
190: {
191: MessageBox.Show("완료되었습니다");
192: }
193: }
194: catch (Exception ex) { throw new Exception("오류가 발생했습니다", ex); }
195: finally
196: {
197: this.btnStart.Enabled = true;
198: this.btnCancel.Enabled = false;
199: this.Cursor = Cursors.Default;
200: }
201: }
202:
203: #endregion
204:
205: }
206: }
207:
208:
209:
210: // Form1.Designer.cs
211: namespace DemoProgressBar
212: {
213: partial class Form1
214: {
215: /// <summary>
216: /// 필수 디자이너 변수입니다.
217: /// </summary>
218: private System.ComponentModel.IContainer components = null;
219:
220: /// <summary>
221: /// 사용 중인 모든 리소스를 정리합니다.
222: /// </summary>
223: /// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
224: protected override void Dispose(bool disposing)
225: {
226: if (disposing && (components != null))
227: {
228: components.Dispose();
229: }
230: base.Dispose(disposing);
231: }
232:
233: #region Windows Form 디자이너에서 생성한 코드
234:
235: /// <summary>
236: /// 디자이너 지원에 필요한 메서드입니다.
237: /// 이 메서드의 내용을 코드 편집기로 수정하지 마십시오.
238: /// </summary>
239: private void InitializeComponent()
240: {
241: this.bgWorker = new System.ComponentModel.BackgroundWorker();
242: this.btnStart = new System.Windows.Forms.Button();
243: this.progressBar = new System.Windows.Forms.ProgressBar();
244: this.btnCancel = new System.Windows.Forms.Button();
245: this.lblWorkCount = new System.Windows.Forms.Label();
246: this.label1 = new System.Windows.Forms.Label();
247: this.SuspendLayout();
248: //
249: // btnStart
250: //
251: this.btnStart.Location = new System.Drawing.Point(13, 13);
252: this.btnStart.Name = "btnStart";
253: this.btnStart.Size = new System.Drawing.Size(75, 23);
254: this.btnStart.TabIndex = 0;
255: this.btnStart.Text = "시작";
256: this.btnStart.UseVisualStyleBackColor = true;
257: //
258: // progressBar
259: //
260: this.progressBar.Dock = System.Windows.Forms.DockStyle.Bottom;
261: this.progressBar.Location = new System.Drawing.Point(0, 76);
262: this.progressBar.Name = "progressBar";
263: this.progressBar.Size = new System.Drawing.Size(284, 23);
264: this.progressBar.Step = 1;
265: this.progressBar.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
266: this.progressBar.TabIndex = 1;
267: //
268: // btnCancel
269: //
270: this.btnCancel.Location = new System.Drawing.Point(94, 13);
271: this.btnCancel.Name = "btnCancel";
272: this.btnCancel.Size = new System.Drawing.Size(75, 23);
273: this.btnCancel.TabIndex = 0;
274: this.btnCancel.Text = "취소";
275: this.btnCancel.UseVisualStyleBackColor = true;
276: //
277: // lblWorkCount
278: //
279: this.lblWorkCount.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
280: this.lblWorkCount.Location = new System.Drawing.Point(94, 39);
281: this.lblWorkCount.Name = "lblWorkCount";
282: this.lblWorkCount.Size = new System.Drawing.Size(75, 23);
283: this.lblWorkCount.TabIndex = 2;
284: this.lblWorkCount.Text = "label1";
285: this.lblWorkCount.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
286: //
287: // label1
288: //
289: this.label1.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
290: this.label1.Location = new System.Drawing.Point(12, 39);
291: this.label1.Name = "label1";
292: this.label1.Size = new System.Drawing.Size(76, 23);
293: this.label1.TabIndex = 2;
294: this.label1.Text = "작업건수 : ";
295: this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
296: //
297: // Form1
298: //
299: this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
300: this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
301: this.ClientSize = new System.Drawing.Size(284, 99);
302: this.Controls.Add(this.label1);
303: this.Controls.Add(this.lblWorkCount);
304: this.Controls.Add(this.progressBar);
305: this.Controls.Add(this.btnCancel);
306: this.Controls.Add(this.btnStart);
307: this.Name = "Form1";
308: this.Text = "비동기실행데모";
309: this.ResumeLayout(false);
310:
311: }
312:
313: #endregion
314:
315: private System.ComponentModel.BackgroundWorker bgWorker;
316: private System.Windows.Forms.Button btnStart;
317: private System.Windows.Forms.ProgressBar progressBar;
318: private System.Windows.Forms.Button btnCancel;
319: private System.Windows.Forms.Label lblWorkCount;
320: private System.Windows.Forms.Label label1;
321: }
322: }
323:
324: // Program.cs
325:
326: using System;
327: using System.Collections.Generic;
328: using System.Linq;
329: using System.Windows.Forms;
330:
331: namespace DemoProgressBar
332: {
333: static class Program
334: {
335: /// <summary>
336: /// 해당 응용 프로그램의 주 진입점입니다.
337: /// </summary>
338: [STAThread]
339: static void Main()
340: {
341: try
342: {
343: Application.EnableVisualStyles();
344: Application.SetCompatibleTextRenderingDefault(false);
345: Application.Run(new Form1());
346: }
347: catch (Exception ex)
348: {
349: MessageBox.Show(ex.Message);
350: }
351: }
352: }
353: }
TRACKBACK URL : http://bbon.kr/blog/trackback/878




