我正在开发一个简单的winforms C#应用程序。我想使用Background Workers在Top上显示一个加载Form,而另一个Background Worker正在向我的WCF服务器进行咨询。
我的WinForms应用程序的工作方式如下: 我有一个MainForm和很多UserControls。当我启动应用程序时,我将LoginUserControl添加到MainForm控件。当我单击LoginUserControl中的“登录按钮”时,我想显示“加载表单”并同时查阅服务器。稍后,我需要向Loading Background Worker发送一个信号,指示Server Consult Background Worker已完成。
我的问题是,我应该为每个需要加载面板的UserControl实现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();
}
}
请注意以下事项:
worker
是Control
子类,所以我通过表单编辑器添加它。这也意味着它的回调是在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();
});