BackgroundWorker Progress更改为从单独的类触发的表单

时间:2012-10-21 03:56:27

标签: c# class backgroundworker

我是C#的新手,我正在尝试围绕面向对象的编程。这就是我想要完成的事情:

我有一个带有Form1的Windows窗体应用程序和一个名为connect(相同命名空间)的单独类。

我理解在执行大量代码时使用后台工作人员是一种好习惯(以免冻结UI)。所以我在Form1中创建了一个后台工作程序和一个progresschanged句柄。我试图找到如何在单独的连接类中触发progresschange。在Form1的progresschange块中,我有一个case / switch,用于确定屏幕上显示的文本。

最好的方法是什么?我可以把背景工作者传给另一个班级吗?

2 个答案:

答案 0 :(得分:5)

您也可以将BackgroundWorker放在Connect类中。在这个课程中,您可以创建事件以将进度和完成情况报告回调用表单。

using System;
using System.ComponentModel;

namespace WindowsTest
{
public class Connect
{
    BackgroundWorker bw;
    public Connect()
    {
        bw = new BackgroundWorker();
        bw.WorkerSupportsCancellation = true;
        bw.WorkerReportsProgress = true;
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        bw.DoWork +=new DoWorkEventHandler(bw_DoWork);
        bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
    }

    public delegate void ProgressChangedHandler(Object sender, ProgressChangedEventArgs e);
    public event ProgressChangedEventHandler ProgressChanged;
    protected void RaiseProgressChangedEvent(ProgressChangedEventArgs e)
    {
        if (ProgressChanged == null)
        {
            return;
        }
        ProgressChanged(this, e);
    }

    public delegate void WorkCompleteEventHandler(Object sender, RunWorkerCompletedEventArgs e);
    public event WorkCompleteEventHandler WorkComplete;
    protected void RaiseWorkCompleteEvent(RunWorkerCompletedEventArgs e)
    {
        if (WorkComplete == null)
        {
            return;
        }
        WorkComplete(this, e);
    }

    public void Cancel()
    {
        if (bw.IsBusy)
        {
            bw.CancelAsync();            
        }
    }

    public void BeginLongRunningProcess()
    {
        bw.RunWorkerAsync();
    }

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        RaiseWorkCompleteEvent(e);
    }

    private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        RaiseProgressChangedEvent(e);
    }

    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        if (ConnectToServer())
        {
            bw.ReportProgress(0, "Connected to server");
            e.Result = LongRunningProcess();
            if (e.Result.ToString() == "Cancelled")
            {
                e.Cancel = true;
                return;
            }
        }
        else
        {
            //Connection failed
            e.Cancel = true;    
        }
    }

    private bool ConnectToServer()
    { 
        //Attempt connection
        return true;
    }

    private string LongRunningProcess()
    {
        int recordCount = 250;
        for (int i = 0; i <= recordCount; i++)
        {
            if (bw.CancellationPending)
            {
                return "Cancelled";
            }
            double progress = ((double)i / (double)recordCount) * 100;
            bw.ReportProgress((int)progress , "Running Process");
            System.Threading.Thread.Sleep(25);
        }
        return "The result is 2";
    }
}
}

然后在您的表单上,您只需处理事件。

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

    Connect connect;

    private void btnConnect_Click(object sender, EventArgs e)
    {
        connect = new Connect();
        connect.ProgressChanged += new ProgressChangedEventHandler(connect_ProgressChanged);
        connect.WorkComplete += new Connect.WorkCompleteEventHandler(connect_WorkComplete);
        connect.BeginLongRunningProcess();
    }

    private void connect_WorkComplete(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled)
        {
            lblStatus.ForeColor = Color.Red;
            lblStatus.Text = string.Format("Status: {0}", "User Cancelled!");
            return;
        }

        if (e.Error != null)
        { 
            //Process exception       
            lblStatus.Text = string.Format("Status: {0}", "Error!");
            lblStatus.ForeColor = Color.Red;
            return;
        }

        lblStatus.Text = string.Format("Status: Complete. {0}", e.Result);
    }

    private void connect_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
        lblStatus.Text = string.Format("Status: {0}", e.UserState.ToString());
    }

    private void btnCancel_Click(object sender, EventArgs e)
    {
        if (connect != null)
        {
            connect.Cancel();
        }
    }        
}
}

请注意,BackgroundWorker.ReportProgress()方法的第二个参数(UserState)可以传递任何对象。它不必是一个字符串。例如,如果从数据库中检索了行/行,则可以通过此方法将行传递回用户界面。对于BackgroundWorker.DoWork方法的e.Result也是如此。

埃里克

答案 1 :(得分:2)

您可以将连接类的步骤分解为单独的方法,并按顺序调用它们,如下所示。您不必从连接类对象触发progresschanged事件。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
     ConnectClass conObject= new ConnectClass();
     backgroundWorker.ReportProgress(30, "Connecting ...");
     conObject.Connect();
     backgroundWorker.ReportProgress(30, "Connected."+"\n Executing query");
     conObject.Execute();
     backgroundWorker.ReportProgress(40, "Execution completed.");
}