C#Backgroundworker继续运行DoWork

以下是我的编码:

Form2 msgForm; private void button3_Click_1(object sender, EventArgs e) { bw.WorkerReportsProgress = true; bw.WorkerSupportsCancellation = true; bw.DoWork += new DoWorkEventHandler(bw_DoWork); bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); msgForm = new Form2(); try { bw.RunWorkerAsync(); msgForm.ShowDialog(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } void bw_DoWork(object sender, DoWorkEventArgs e) { // Coding that transmit protocol and will last around 2 minutes. } void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { msgForm.Close(); } 

每次单击按钮发送持续约2分钟的协议时,我都会使用后台工作方法。 在传输过程中,From2将显示“Please wait”。

但是我使用这种编码有一些问题。 问题是,当我第一次点击按钮时,它会发送一次协议。 之后我再次点击这是第二次,它传输协议两次。 之后我再次点击这是第三次,它传输协议3次……依此类推。 每次单击按钮时,传输协议的次数都会增加。

是不是每次我点击按钮时它只会在void bw_DoWork中编码一次?

我的编码有问题吗?

每次单击时,您都会附加一个额外的处理程序,然后它会与之前添加的所有内容一起运行,并保持原样(因为对象仍在那里,您正在重新使用它)。

要解决此问题,您需要:

  • 在方法中移动后台worker的声明(所以每次都是新的,只有一个DoWork处理程序

像这样:

 private void button3_Click_1(object sender, EventArgs e) { BackgroundWorker bw = new BackgroundWorker(); // rest of your code } 
  • 移动.DoWork += ...将处理程序附加到类的构造函数中

这主要取决于你是否在其他地方使用该工作人员。

看起来新员工每次点击都会启动。 要避免此行为,请在再次启动之前检查工作人员是否正忙。

 try { if (!bw.IsBusy) bw.RunWorkerAsync(); } catch (Exception ex) { MessageBox.Show(ex.Message); } 

你可以在backgroundworker完成工作时禁用按钮,按钮button3.Enabled = false; 并在bw_RunWorkerCompleted方法中重新启用它,让用户理解他必须等待,并且在该过程完成之前无法再次单击。

首先确保在传输代码之前清除列表/集合。 然后在源代码中使用BreakPoint并记住,由于使用ShowDialog,BackgroundWorker无法运行两次或更多次。

检查工人是否忙碌:

  if (!bw.IsBusy) bw.RunWorkerAsync(); 

我也会禁用该按钮,并在处理过程中将文本更改为例如“正在运行”。

使用bw_RunWorkerCompleted方法事件调用,然后重新启用该按钮并更改文本。 此方法在与UI相同的线程上运行,因此不存在交叉线程问题。

在您的设计上,为什么要显示“请稍候”通知的其他表单? 我建议在异步进程启动之前更新现有表单上的标签(因此不要跨线程UI问题),或者如果之后需要更新,则可以使用以下内容:

 lblNotify.Invoke(new Action(() => lblNotify.Text = @"Please wait")); 

以上将允许您在主线程上运行您的请求。