2016年5月1日 星期日

[.NET] WPF使用BackgroundWorker實現非同步作業

說明:BackgroundWorker是.NET framewrok 2.0時就有的控制項,方便用於UI thread外,另開thread背景執行耗時的作業,如下載網路上的資料等。


用法:
using System.ComponentModel;

//declare BackgroundWorker object in Field
private readonly BackgroundWorker worker = new BackgroundWorker();

//subscribe events & assign property
public MainWindow()
{
    worker.DoWork += worker_DoWork;
    worker.RunWorkerCompleted += worker_RunWorkerCompleted;
    worker.ProgressChanged += worker_ProgressChanged;
    worker.WorkerReportsProgress = true;
    worker.WorkerSupportsCancellation = true;
}

//下載button
private void btnDownload_Click(object sender, RoutedEventArgs e)
{
    if (!worker.IsBusy)
    {
        //trigger DoWork event
        worker.RunWorkerAsync();
    }
    else
    {
         MessageBox.Show("背景下載作業執行中,請稍候!");
         return;
    }
}

//取消下載button
private void btnCancelDownload_Click(object sender, RoutedEventArgs e)
{
    worker.CancelAsync();
}

#region event handler method

private void worker_DoWork(object sender, DoWorkEventArgs e)
{
     //背景耗時作業
    Download(sender as BackgroundWorker);
         
    if (worker.CancellationPending)
    {
        e.Cancel = true;
        return;
    }
    else
    {
        e.Result = "Download Completed";
    }
}

//DoWork結束後觸發 屬UI Thread
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    //從DoWorkEventArgs object取得傳遞引數e
    //label binding
    this.lblDownloadProgress.Content = (e.Cancelled) ? "Canceled" : e.Result.ToString();
}

//屬UI Thread
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    //label binding
    this.lblDownloadProgress.Content = e.UserState.ToString();
    //progressbar binding
    this.pbDownload.Value = e.ProgressPercentage;
}

#endregion

private void Download(BackgroundWorker worker)
{
    for (int i = 0; i < data.Length; i++)
    {
        if (worker.CancellationPending)
        {
            return;
        }
        else
        {
            //觸發ProgressChanged event
            worker.ReportProgress(i * 100 / data.Length, string.Format("{0} files download", i));
        }
    Thread.Sleep(100);
    }
}


參考資料:
http://stackoverflow.com/questions/5483565/how-to-use-wpf-background-worker
https://msdn.microsoft.com/zh-tw/library/cc221403(VS.95).aspx
https://dotblogs.com.tw/billchung/2009/05/29/8592

沒有留言:

張貼留言