数字运算线程的高效取消事件实现?

时间:2010-08-05 18:48:29

标签: c# multithreading events

在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取消),但我仍然希望尽可能优化这种紧缩方法。任何更有效地完成此操作的示例都会非常好看。

5 个答案:

答案 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)

我会以同样的方式做到这一点。我还会将Thread.Sleep添加到循环中以控制主线程。

http://msdn.microsoft.com/en-us/library/7a2f3ay4%28VS.80%29.aspx