利用BackgroundWorker实现通用并行处理进度对话框

四核的CPU普及了,.NET 4.0来了,并行编程似乎变得越来越普遍了。在最近的一个项目里,我尝试着引入了.NET 4.0在并行处理方面提供的一些新的技术,使代码更加简洁,也更易维护了。

在典型的后台查询、前台显示查询进度的对话框设计上,依照以往的方式,我通常是利用delegate.BeginInvoke()方法,通过预定的Callback方法实现UI更新。而使用BackgroundWorker这个类,实现了基于事件的异步模式之后,这项工作变得轻松了许多。

以下是我用Winform实现的一个简单示例,尽可能地保证了显示进度对话框的封闭性和代码简洁性。

源代码下载(7zip压缩)


一、显示进度对话框ProgressDlg的实现

public partial class ProgressDlg : Form
{
    public ProgressDlg()
    {
        InitializeComponent();
    }

    public void OnProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // show the progress.
        this.progressBar.Value = e.ProgressPercentage;
    }

    public void OnCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // thread is completed, close the dialog.
        this.progressBar.Value = 100;
        this.Close();
    }

    public CancelEventHandler OnCancel = null;

    private void btnCancel_Click(object sender, EventArgs e)
    {
        // thread is cancelled, close the dialog.
        this.Close();
    }

    private void ProgressDlg_FormClosed(object sender, FormClosedEventArgs e)
    {
        // cast notification of cancellation.
        if (this.OnCancel != null)
            this.OnCancel(this, new CancelEventArgs());
    }
}

二、主窗口MainForm的实现

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();

        this._backworker = new BackgroundWorker();
        // it's neccessary to set the properties.
        this._backworker.WorkerReportsProgress = true;
        this._backworker.WorkerSupportsCancellation = true;

        this._backworker.DoWork += new DoWorkEventHandler(backworker_DoWork);
        this._backworker.ProgressChanged += new ProgressChangedEventHandler(backworker_ProgressChanged);
        this._backworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backworker_RunWorkerCompleted);
    }

    private BackgroundWorker _backworker = null;        

    // body of thread
    void backworker_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 0; i < 100; i++)
        {
            Thread.Sleep(100);

            // trigger the event: ProgressChanged
            this._backworker.ReportProgress(i);

            // if receive the notification of Cancel.
            if (this._backworker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
        }
    }

    void backworker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // to do nothing.
    }

    void backworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // if thread is completed because of cancellation.
        if (e.Cancelled)
            this.labelSummary.Text = "Calculation is cancelled";

        this.btnCalculate.Enabled = true;
    }

    void backworker_OnCancel(object sender, CancelEventArgs e)
    {
        this._backworker.CancelAsync();            
    }

    private void btnCalculate_Click(object sender, EventArgs e)
    {
        string temp = this.txtMax.Text.Trim();
        if (string.IsNullOrEmpty(temp))
            MessageBox.Show("Please input a valid integer.", "Validation", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        else
        {
            ProgressDlg progressDlg = new ProgressDlg();
            // if thread is executing, dialog will show the progress.
            this._backworker.ProgressChanged += new ProgressChangedEventHandler(progressDlg.OnProgressChanged);
            this._backworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(progressDlg.OnCompleted);
            // if cancel in progressDlg, let me know and do something.
            progressDlg.OnCancel += new CancelEventHandler(backworker_OnCancel);

            this.btnCalculate.Enabled = false;
            progressDlg.Show();
                
            // start the thread.
            this._backworker.RunWorkerAsync();
        }
    }
}

转载请注明出处及作者,谢谢!
原文地址:https://www.cnblogs.com/Abbey/p/2174136.html