背景工人怀疑

时间:2014-01-23 16:34:12

标签: c# .net winforms wcf backgroundworker

我正在开发一个简单的winforms C#应用程序。我想使用Background Workers在Top上显示一个加载Form,而另一个Background Worker正在向我的WCF服务器进行咨询。

我的WinForms应用程序的工作方式如下: 我有一个MainForm和很多UserControls。当我启动应用程序时,我将LoginUserControl添加到MainForm控件。当我单击LoginUserControl中的“登录按钮”时,我想显示“加载表单”并同时查阅服务器。稍后,我需要向Loading Background Worker发送一个信号,指示Server Consult Background Worker已完成。

我的问题是,我应该为每个需要加载面板的UserControl实现2个后台工作程序吗?以及如何实现背景工作者之间的沟通?

2 个答案:

答案 0 :(得分:1)

  

稍后,我需要向Loading Background Worker发送一个信号,指示Server Consult Background Worker已完成。

不,你不需要。

后台工作者就是它所说的:一个在后台执行任务的“工人”。您的案例中的任务是与您拥有的WCF服务进行通信的方法。工作将在工作完成时结束(或抛出异常)。所以事件的顺序如下:

  • 启动工作人员(如果您的表单是模态的,则必须是第一个)
  • 显示表单
  • 收听工作人员RunWorkerCompleted事件以隐藏表单

事实上,我已经创建了一个类似于此的表单,只是我不与服务器通信(实际上并不重要),并且我显示了一个简单的进度条。

public partial class FastForwardForm : Form
{
    private Exception asyncError;

    public event DoWorkEventHandler DoWork
    {
        add { worker.DoWork += value; }
        remove { worker.DoWork -= value; }
    }

    public FastForwardForm()
    {
        InitializeComponent();
    }

    public Exception AsyncError
    {
        get { return asyncError; }
    }

    private void FastForwardForm_Shown(object sender, EventArgs e)
    {
        worker.RunWorkerAsync();
    }

    private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar.Value = e.ProgressPercentage;
        statusLabel.Text = e.UserState.ToString();
    }

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null) asyncError = e.Error;
        HideProgressForm();
        worker.Dispose();
    }

    private void HideProgressForm()
    {
        //not actually needed, the callback runs on the UI thread.
        if (InvokeRequired)
        {
            Invoke((Action)HideProgressForm);
            return;
        }
        Close();
    }
}

请注意以下事项:

  • workerControl子类,所以我通过表单编辑器添加它。这也意味着它的回调是在UI线程上执行的,而你需要我添加的if (InvokeRequired)部分。不要问我为什么会这样,我在重构后错过了它。)
  • 表格会为您完成一些肮脏的工作:一旦显示工人,就立即开始工作。存储该过程的例外。公开DoWork,以便您可以从表单外的任何位置添加后台工作。
  • 代码并不完美:如果您需要重复使用表单,则必须删除worker.Dispose();并将其添加到表单Dispose()方法。

现在,如果您需要在表单中显示一些“等待”动画,则不需要其他工作人员。你需要一个Timer控件来刷新动画,但这是另一个故事。

答案 1 :(得分:0)

首先,从Form开始BackgroundWorker是一个坏主意。这会干扰Windows Forms所具有的单个UI线程。

您最好从UI线程中打开Form,然后从Invoke致电BackgroundWorker以关闭表单。

form.Invoke((MethodInvoker)delegate()
{
    busyForm.Close();
});