Study/C#

C# Windows Forms 강의 11편: Timer와 BackgroundWorker

wawManager 2025. 2. 14. 12:00
728x90

1. 강의 개요

이번 강의에서는 Windows Forms에서 비동기 작업과 주기적인 작업을 처리하는 데 유용한 TimerBackgroundWorker를 학습합니다.

  • Timer: 일정 시간 간격으로 이벤트를 발생시키는 컨트롤.
  • BackgroundWorker: 별도의 스레드에서 백그라운드 작업을 수행하고 UI와 안전하게 통신.

2. 학습 목표

  1. Timer를 사용해 주기적으로 실행되는 작업을 구현.
  2. BackgroundWorker로 비동기 작업을 처리하고 UI를 업데이트하는 방법 학습.
  3. Timer와 BackgroundWorker를 결합하여 복잡한 작업을 주기적으로 처리.

3. Timer (타이머)

Timer란?

Timer는 설정된 간격마다 이벤트를 발생시키는 컨트롤입니다.

  • 작업 예약, 애니메이션, 자동 업데이트 등에 사용.

주요 속성

속성 설명 예제

Interval 타이머 간격 설정 (밀리초) timer1.Interval = 1000;
Enabled 타이머 동작 여부 timer1.Enabled = true;

주요 이벤트

이벤트 설명 예제

Tick Interval에 설정된 시간마다 발생하는 이벤트 timer1.Tick += Timer1_Tick;

4. BackgroundWorker (백그라운드 워커)

BackgroundWorker란?

BackgroundWorker는 UI와 독립된 스레드에서 작업을 수행하는 컨트롤입니다.

  • 백그라운드 작업을 수행하고, 작업 완료 또는 진행 상태를 UI와 안전하게 통신.

주요 속성

속성 설명 예제

WorkerReportsProgress 진행률 보고 가능 여부 설정 backgroundWorker1.WorkerReportsProgress = true;
WorkerSupportsCancellation 작업 취소 가능 여부 설정 backgroundWorker1.WorkerSupportsCancellation = true;

주요 이벤트

이벤트 설명 예제

DoWork 백그라운드 작업 수행 backgroundWorker1.DoWork += BackgroundWorker1_DoWork;
ProgressChanged 진행 상태가 보고될 때 발생 backgroundWorker1.ProgressChanged += BackgroundWorker1_ProgressChanged;
RunWorkerCompleted 작업이 완료되었을 때 발생 backgroundWorker1.RunWorkerCompleted += BackgroundWorker1_RunWorkerCompleted;

5. 실습: Timer와 BackgroundWorker 사용하기

요구사항

  1. Timer를 사용해 Label에 현재 시간을 매초 업데이트.
  2. BackgroundWorker로 무거운 작업(예: 숫자 계산)을 백그라운드에서 처리.
  3. 작업 진행 상태를 ProgressBar에 표시하고, 작업 완료 시 메시지 출력.

폼 구성

컨트롤 타입 이름 텍스트 위치 크기

Label lblTime (현재 시간 표시) (10, 20) (300 x 30)
Button btnStartWork "작업 시작" (10, 60) (150 x 30)
ProgressBar progressBar1 (없음) (10, 100) (300 x 30)

코드 작성

Form1.cs

using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            InitializeTimer();
            InitializeBackgroundWorker();
        }

        private Timer timer1;
        private BackgroundWorker backgroundWorker1;

        private void InitializeTimer()
        {
            // Timer 설정
            timer1 = new Timer();
            timer1.Interval = 1000; // 1초 간격
            timer1.Tick += Timer1_Tick;
            timer1.Start();
        }

        private void InitializeBackgroundWorker()
        {
            // BackgroundWorker 설정
            backgroundWorker1 = new BackgroundWorker();
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.WorkerSupportsCancellation = true;

            backgroundWorker1.DoWork += BackgroundWorker1_DoWork;
            backgroundWorker1.ProgressChanged += BackgroundWorker1_ProgressChanged;
            backgroundWorker1.RunWorkerCompleted += BackgroundWorker1_RunWorkerCompleted;
        }

        // Timer 이벤트 핸들러: 현재 시간 표시
        private void Timer1_Tick(object sender, EventArgs e)
        {
            lblTime.Text = $"현재 시간: {DateTime.Now:HH:mm:ss}";
        }

        // Button 클릭 이벤트: 작업 시작
        private void BtnStartWork_Click(object sender, EventArgs e)
        {
            if (!backgroundWorker1.IsBusy)
            {
                progressBar1.Value = 0;
                backgroundWorker1.RunWorkerAsync();
                MessageBox.Show("작업을 시작합니다.", "작업 시작");
            }
        }

        // BackgroundWorker의 DoWork: 백그라운드 작업 수행
        private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; i <= 100; i++)
            {
                if (backgroundWorker1.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }

                // 작업 진행 중 (작업 시뮬레이션)
                Thread.Sleep(50); // 50ms 지연
                backgroundWorker1.ReportProgress(i);
            }
        }

        // BackgroundWorker의 ProgressChanged: 진행 상태 업데이트
        private void BackgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }

        // BackgroundWorker의 RunWorkerCompleted: 작업 완료 처리
        private void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                MessageBox.Show("작업이 취소되었습니다.", "취소");
            }
            else
            {
                MessageBox.Show("작업이 완료되었습니다!", "완료");
            }
        }
    }
}

6. 실행 결과

  1. Timer
    • Label에 현재 시간이 매초 업데이트됩니다.
    • 예: 현재 시간: 15:23:10.
  2. BackgroundWorker
    • "작업 시작" 버튼을 클릭하면 ProgressBar가 0%에서 100%로 점진적으로 증가합니다.
    • 작업이 완료되면 "작업이 완료되었습니다!" 메시지가 표시됩니다.
  3. 진행 상태 취소 (확장)
    • BackgroundWorker의 CancellationPending을 사용해 작업을 취소할 수 있습니다.

7. 주요 개념 요약

  1. Timer는 주기적으로 실행되는 작업을 간단히 구현할 수 있으며, Tick 이벤트로 작업을 처리.
  2. BackgroundWorker는 UI 스레드와 독립된 작업을 수행하며, 작업 상태를 보고하고 UI를 안전하게 업데이트 가능.
  3. Timer와 BackgroundWorker를 결합해 실시간 상태 업데이트와 비동기 작업을 동시에 처리 가능.
728x90