🔎 유용한 정보
1. 강의 개요
이번 강의에서는 다중 쓰레드와 ProgressBar를 결합하여 긴 작업을 처리하면서 UI의 응답성을 유지하는 방법을 학습합니다.
특히, Thread 클래스와 Invoke 메서드를 사용해 UI를 안전하게 업데이트하고, 작업 진행 상태를 표시하는 애플리케이션을 구현합니다.
2. 학습 목표
- Thread 클래스를 사용해 긴 작업을 비동기로 실행.
- ProgressBar로 작업 진행 상태를 UI에 표시.
- UI 업데이트 시 발생할 수 있는 쓰레드 충돌 문제 해결.
3. 다중 쓰레드와 UI 업데이트
다중 쓰레드 개념
- UI 쓰레드: 폼과 컨트롤의 이벤트를 처리하는 주 쓰레드.
- 백그라운드 쓰레드: UI와 독립적으로 실행되는 작업 쓰레드.
Invoke 메서드
- UI 컨트롤은 UI 쓰레드에서만 업데이트 가능.
- 백그라운드 쓰레드에서 UI를 안전하게 업데이트하려면 Control.Invoke 메서드를 사용해야 함.
4. 실습: 다중 쓰레드로 작업 처리 및 ProgressBar 업데이트
요구사항
- Thread 클래스를 사용해 긴 작업(파일 처리 시뮬레이션) 비동기 실행.
- ProgressBar로 작업 진행 상태 표시.
- 작업 중에도 UI가 응답성을 유지.
폼 구성
컨트롤 타입 이름 텍스트 위치 크기
ProgressBar | progressBar1 | (없음) | 중앙 | (300 x 30) |
Button | btnStart | "작업 시작" | 하단 왼쪽 | (100 x 30) |
Button | btnCancel | "작업 취소" | 하단 오른쪽 | (100 x 30) |
코드 작성
1. Form1.cs
using System;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private Thread workerThread; // 작업을 실행할 쓰레드
private bool cancelRequested; // 작업 취소 여부 확인 변수
public Form1()
{
InitializeComponent();
InitializeEvents();
}
private void InitializeEvents()
{
btnStart.Click += BtnStart_Click;
btnCancel.Click += BtnCancel_Click;
}
// "작업 시작" 버튼 클릭 이벤트
private void BtnStart_Click(object sender, EventArgs e)
{
if (workerThread == null || !workerThread.IsAlive)
{
cancelRequested = false; // 작업 취소 플래그 초기화
progressBar1.Value = 0; // ProgressBar 초기화
workerThread = new Thread(DoWork);
workerThread.IsBackground = true; // 백그라운드 쓰레드 설정
workerThread.Start();
}
}
// "작업 취소" 버튼 클릭 이벤트
private void BtnCancel_Click(object sender, EventArgs e)
{
if (workerThread != null && workerThread.IsAlive)
{
cancelRequested = true; // 작업 취소 요청
}
}
// 긴 작업 처리 메서드 (백그라운드 쓰레드에서 실행)
private void DoWork()
{
for (int i = 1; i <= 100; i++)
{
if (cancelRequested) // 작업 취소 요청 확인
{
UpdateStatus("작업이 취소되었습니다.");
return;
}
Thread.Sleep(50); // 작업 시뮬레이션 (50ms 대기)
UpdateProgress(i); // ProgressBar 업데이트
}
UpdateStatus("작업이 완료되었습니다!"); // 작업 완료 메시지
}
// ProgressBar 업데이트 (UI 쓰레드에서 실행)
private void UpdateProgress(int value)
{
if (progressBar1.InvokeRequired)
{
progressBar1.Invoke(new Action(() => progressBar1.Value = value));
}
else
{
progressBar1.Value = value;
}
}
// 작업 상태 메시지 업데이트 (UI 쓰레드에서 실행)
private void UpdateStatus(string message)
{
if (InvokeRequired)
{
Invoke(new Action(() => MessageBox.Show(message, "상태")));
}
else
{
MessageBox.Show(message, "상태");
}
}
}
}
2. Form1.Designer.cs
namespace WindowsFormsApp1
{
partial class Form1
{
private System.ComponentModel.IContainer components = null;
private ProgressBar progressBar1;
private Button btnStart;
private Button btnCancel;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.progressBar1 = new ProgressBar();
this.btnStart = new Button();
this.btnCancel = new Button();
this.SuspendLayout();
// progressBar1
this.progressBar1.Location = new System.Drawing.Point(20, 20);
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(300, 30);
this.progressBar1.TabIndex = 0;
// btnStart
this.btnStart.Location = new System.Drawing.Point(20, 70);
this.btnStart.Name = "btnStart";
this.btnStart.Size = new System.Drawing.Size(100, 30);
this.btnStart.Text = "작업 시작";
this.btnStart.UseVisualStyleBackColor = true;
// btnCancel
this.btnCancel.Location = new System.Drawing.Point(220, 70);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(100, 30);
this.btnCancel.Text = "작업 취소";
this.btnCancel.UseVisualStyleBackColor = true;
// Form1
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(350, 120);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnStart);
this.Controls.Add(this.progressBar1);
this.Name = "Form1";
this.Text = "다중 쓰레드 예제";
this.ResumeLayout(false);
}
}
}
5. 실행 결과
- 초기 상태
- ProgressBar는 비어 있고, "작업 시작"과 "작업 취소" 버튼이 표시됩니다.
- 작업 시작
- "작업 시작" 버튼 클릭 → ProgressBar가 점차 채워지며 작업이 진행됩니다.
- 작업 중에도 UI는 응답성을 유지합니다.
- 작업 완료
- ProgressBar가 끝까지 채워지면 "작업이 완료되었습니다!" 메시지가 표시됩니다.
- 작업 취소
- "작업 취소" 버튼 클릭 → 작업이 중단되고 "작업이 취소되었습니다." 메시지가 표시됩니다.
6. 주요 개념 요약
- Thread 클래스
- 긴 작업을 백그라운드 쓰레드에서 실행하여 UI 스레드의 응답성을 유지.
- Invoke 메서드
- UI 업데이트는 UI 스레드에서만 가능하므로 Invoke를 사용해 안전하게 호출.
- 작업 취소 처리
- cancelRequested 플래그를 사용해 작업 취소 로직 구현.
'📁 [4] 개발자 정보 & 코드 노트 > C#' 카테고리의 다른 글
C# Windows Forms 강의 52편: To-Do List 애플리케이션 제작 (0) | 2025.03.27 |
---|---|
C# Windows Forms 강의 51편: 메모장 애플리케이션 제작 (0) | 2025.03.26 |
C# Windows Forms 강의 49편: 데이터 바인딩과 DataGridView 고급 사용 (0) | 2025.03.24 |
C# Windows Forms 강의 48편: 리소스 관리 (이미지, 아이콘, 사운드 파일) (0) | 2025.03.23 |
C# Windows Forms 강의 47편: 폼 간 데이터 전달 방법 (0) | 2025.03.22 |
🔎 유용한 정보