此代码的目的是接受表单中的文本,将其传递给函数,并将此文本存储在将执行第二个函数的后台工作程序中。此后台工作程序已定义其do_work和work_completed事件侦听器。问题是当我第一次运行应用程序运行此代码时,它工作正常。下次我执行“fetchFunction”并随后执行fetchStuff函数时,我得到2个窗口或2个objfrmMChild,而不是像我第一次运行它时那样。
我在调试模式下运行我的代码并看到RunWorkerCompletedEventHandler运行一次然后弹出窗口,然后它再次循环并再次运行。知道为什么吗?
public void fetchFunction(TextBox text)
{
fetch.WorkerSupportsCancellation = true;
if (!fetch.IsBusy)
{
Lists.BGWParams bgwp = new Lists.BGWParams();
bgwp.Value = text.Text.Trim();
fetchStuff(bgwp);
}
else
{
fetch.CancelAsync();
}
}
private void fetchStuff(Lists.BGWParams parameters)
{
DoWorkEventHandler dweh = (object senderA, DoWorkEventArgs argsA) =>
{
if (argsA != null && argsA.Argument is Lists.BGWParams)
{
Lists.BGWParams p = argsA.Argument as Lists.BGWParams;
p.Result2 = genericClass.fetchOtherStuff_DoWork(p.Value);
argsA.Result = argsA.Argument;
}
};
RunWorkerCompletedEventHandler rwceh = (object senderB, RunWorkerCompletedEventArgs argsB) =>
{
if (argsB != null && argsB.Result is Lists.BGWParams)
{
Lists.BGWParams p = argsB.Result as Lists.BGWParams;
frmMChild objfrmMChild = new frmMChild(this);
countResults = p.Result2;
objfrmMChild.MdiParent = this;
objfrmMChild.Show();
objfrmMChild.populateDataGridwithStuff(p.Result2, p.Value);
}
};
fetch.DoWork += dweh;
fetch.RunWorkerCompleted += rwceh;
fetch.RunWorkerAsync(parameters);
}
答案 0 :(得分:2)
您的fetchStuff
正在引用作为实例字段的BackgroundWorker
。每次调用fetchStuff
时,您都会为每个事件添加另一个处理程序。第一次有一次,第二次有两次,第三次有三次。你多次做这项工作,并多次显示结果。
只需将BGW置于该方法的本地。如果您每次没有这个问题就创建一个新的BGW。如果你这样做,你仍然需要支持取消。最简单的方法是创建一个CancellationTokenSource
作为BGW使用的字段。每次开始操作时都创建一个新的CTS。 (也就是说,您从未在DoWork
处理程序中检查取消,因此您实际上并未取消任何内容。)
另一种方法是在创建此类时附加这些事件处理程序,而不是在fetchStuff
内部; fetchStuff
只需致电RunWorkerAsync
。 (或者就此而言,完全省略它,并且可以调用它RunWorkeAsync
。)