2013/03/01

C#.Net 非同步執行緒

非同步執行緒在網頁上還蠻常見的,在一般程式設計則要去看程式需求去實做非同步執行緒

非同步執行緒實做方法其實不難,首先要加入一個BackgroundWorker元件

在程式載入時我們就應該支援『非同步取消執行緒』,『可回報目前進度』其實要看使用者的需求

//支援非同步取消 
backgroundWorker1.WorkerSupportsCancellation = true;

//可報告目前進度
backgroundWorker1.WorkerReportsProgress = true;




那執行緒的工作應該放在哪個事件中呢?就放在DoWork裡面

有啟動可回報進度的使用者可以實做ProgressChanged事件,在事件裡去處理



RunWorkerCompleted事件裡則可以去處理到取消、錯誤以及完成時會在觸發哪些事件







using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace testTheard
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            //支援非同步取消
            backgroundWorker1.WorkerSupportsCancellation = true;

            //可報告目前進度
            backgroundWorker1.WorkerReportsProgress = true;
            progressBar1.Minimum = 0;
            progressBar1.Maximum = 50;
            progressBar1.Value = 0;
            buttonStop.Enabled = false;
            buttonStart.Enabled = true;
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            buttonStart.Enabled = false;
            buttonStop.Enabled = true;

            //當執行緒不忙碌時
            if (backgroundWorker1.IsBusy != true)
            {
                //開始作業
                backgroundWorker1.RunWorkerAsync();
            }
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            buttonStop.Enabled = false;
            buttonStart.Enabled = true;

            //當使用非同步時
            if (backgroundWorker1.WorkerSupportsCancellation == true)
            {
                //取消非同步
                backgroundWorker1.CancelAsync();
            }
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = (BackgroundWorker)sender;
            for (int i = 1; i <= 25; i++)
            {
                //如果有取消訊號
                if (worker.CancellationPending == true)
                {
                    //取消該事件並跳出迴圈
                    e.Cancel = true;
                    break;
                }
                else
                {
                    //0.5秒執行一次
                    System.Threading.Thread.Sleep(500);

                    //回報進度=i*2
                    worker.ReportProgress(i * 2);
                }
            }
        }

        //當非同步執行緒在執行時
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //如果取消
            if (e.Cancelled == true)
            {
                MessageBox.Show("Canceled!");
            }

            //如果錯誤
            else if (e.Error != null)
            {
                MessageBox.Show("Error: " + e.Error.Message);
            }

            //如果完成
            else
            {
                MessageBox.Show("Done!");
                progressBar1.Value = 0;
                buttonStop.Enabled = false;
                buttonStart.Enabled = true;
            }
        }
    }
}



參考資料:
http://support.microsoft.com/kb/315582/zh-tw
http://msdn.microsoft.com/zh-tw/library/2e08f6yc(v=vs.80).aspx
http://msdn.microsoft.com/zh-tw/library/windows/apps/hh452713.aspx
http://www.dotblogs.com.tw/kirkchen/archive/2010/12/28/20435.aspx
http://msdn.microsoft.com/zh-tw/library/system.componentmodel.backgroundworker.aspx
http://msdn.microsoft.com/zh-tw/library/system.componentmodel.backgroundworker.progresschanged.aspx