Window/WPF2010. 7. 11. 15:46

어떤 작업이 오래 걸리는 경우 사용자에게 현재 진행률을 보여줘야 하는 경우가 있습니다.

이 경우에 사용할 수 있는 쓰레드가 BackgroundWorker 입니다.

백그라운드에서 비동기적으로 실행이 되는 동안 호출 스레드는 계속 정상적으로 실행이 됩니다.
 
현재 진행률을 설정할 수 있으며 작업이 완료된 시점의 이벤트를 발생할 수 있습니다.
중간에 작업을 취소할 수도 있습니다.

예제로 간단하게 버튼을 누르면 0에서 100까지의 진행률을 보여주며 중간에 Cancle 버튼을 누르면 작업이
취소되도록 하였습니다. UI 작업을 보여주기 위해 작업 동안 Ellipse를 랜덤하게 뿌려주게 하였습니다.
 
소스는 다음과 같습니다.

 public partial class Window1 : Window

{

    private BackgroundWorker thread = new BackgroundWorker();

    private readonly int max = 100;

    private BrushConverter brushConverter = new BrushConverter();

    private Random random = new Random();

 

    public Window1()

    {

        InitializeComponent();

    }

 

    protected override void OnInitialized(System.EventArgs e)

    {

        base.OnInitialized(e);

 

        progress.Maximum = max;

 

        // 진행률 전송 여부

        thread.WorkerReportsProgress = true;

 

        // 작업 취소 여부

        thread.WorkerSupportsCancellation = true;

 

        // 작업 쓰레드

        thread.DoWork += new DoWorkEventHandler(thread_DoWork);

 

        // 진행률 변경

        thread.ProgressChanged += new ProgressChangedEventHandler(thread_ProgressChanged);

 

        // 작업 완료

        thread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(thread_RunWorkerCompleted);

    }

 

    void thread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

    {

        btnStart.Content = "Start";

        string result = "작업이 완료되었습니다.";

 

        // 작업이 취소된 경우

        if (e.Cancelled)

        {

            result = "작업이 취소되었습니다.";

        }

 

        MessageBox.Show(result);

    }

 

    void thread_ProgressChanged(object sender, ProgressChangedEventArgs e)

    {

        int value = e.ProgressPercentage;

 

        // 변경 값으로 갱신

        progress.Value =value;

        progressValue.Text = value.ToString() + "%";

    }

 

    void thread_DoWork(object sender, DoWorkEventArgs e)

    {

        BackgroundWorker worker = sender as BackgroundWorker;

 

        for (int i = 0; i <= max; i++)

        {

            // CancelAsync() 메서드가 호출되었다면 정지

            if (worker.CancellationPending == true)

            {

                e.Cancel = true;

                break;

            }

            else

            {

                System.Threading.Thread.Sleep(50);

 

                // UI 쓰레드에 접근

                this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()

                {

                    ellipseGrid.Children.Add(RandomEllipse());

                });

 

 

                // 진행률 변경 값 전송

                worker.ReportProgress(i);

            }

        }

    }

 

[ 작업 진행 화면 ]

 

[ 작업 완료 화면 ]

 

[ 작업 취소 화면 ]

Posted by 열ㅇl