在C#程序中创建“取消”事件的最有效方法是什么?在单独的线程上循环处理大量数据?
现在,我只是使用从我的UI线程触发的取消事件,该线程随后在数字运算线程上调用“onCancel”函数。该取消函数将变量设置为“真”,紧缩循环定期检查,例如
Class Cruncher {
private bool cancel = false;
public cruncher()
{
crunch();
}
private void crunch()
{
while(conditions AND !cancel) { crunch; }
dispose_resources;
}
private void onCancel()
{
cancel = true;
}
}
虽然我没有像上面的示例那样频繁地检查取消变量(并且实际上没有执行NOT取消),但我仍然希望尽可能优化这种紧缩方法。任何更有效地完成此操作的示例都会非常好看。
答案 0 :(得分:3)
取消事件/标记应为volatile
...我向您提出了一个非常类似的问题:Is it safe to use a boolean flag to stop a thread from running in C#
我还建议您在取消线程时使用类似C# version of CountDownLatch的内容等待所有线程取消。当你想要保证线程被取消时,这很有用。
答案 1 :(得分:1)
最终总会产生类似的结果 - 尽管让cancel
变量变为易变重要,否则工作线程可能看不到取消线程的变化。
你必须定期检查某事,除非你想采用更激烈的中断线程的路线(我不推荐)。检查单个布尔标志可能不是很昂贵......如果你可以在循环的每次迭代中做一个合理的工作(足以使检查的成本相形见绌),那就没问题了。
如果您需要执行任何等待,但是(在工作线程中)然后您可以通过使用等待形式(例如Monitor.Wait
)来改善问题它允许取消线程提前唤醒任何等待的线程。这不会使正常操作更有效,但它将允许线程在取消时更快地终止。
答案 2 :(得分:1)
特别是因为它是由UI触发的,我建议只利用框架中已经存在的BackgroundWorker,特别是因为它很好地为你创建了进程并在UI线程上完成了事件(所以你不要不得不自己调用它。)
然后你可以使用CancelAsync()调用。不可否认,它与您已经在做的事情没什么不同,只是在框架中完成(包括线程同步逻辑)
正如Jon所说,你仍然希望合作取消(在你的DoWork中检查CancellationPending以使用BackgroundWorker),因为如果可能的话,你想要避免'中断/中止线程'选项。
如果在.NET 4中你可以使用TPL和new Cancellation support,但它再次专注于合作取消。
答案 3 :(得分:1)
我建议使用.NET 4.0中引入的unified cancellation model(如果选择.NET 4.0)。
非常高效,允许使用Task
个对象和Parallel LINQ进行集成取消。
答案 4 :(得分:0)
http://msdn.microsoft.com/en-us/library/7a2f3ay4%28VS.80%29.aspx