2010-08-05 40 views
3

什么是在一个C#程序中创建一个“取消”事件的最有效方法,该程序正在一个单独的线程上处理一个循环中的大量数据集?有效取消数字处理线程的事件实现?

现在,我只是简单地使用从我的UI线程触发的cancel事件,该事件随后在数字运算线程上调用“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; 
    } 
} 

虽然我没有检查经常取消变量作为我的榜样以上(而不是实际执行不取消),我还是想优化这个紧缩方法尽可能。任何更有效地完成这个例子的例子都会很好看。

+1

在非常紧密的循环中,我通过仅检查每100或1000次迭代而不是每次迭代来进行优化。但你必须检查。 – 2010-08-05 22:04:31

回答

3

取消事件/标志应该是一个volatile ......我问了一个非常类似的问题给你:Is it safe to use a boolean flag to stop a thread from running in C#

我也建议您何时取消线程你等待他们都用取消类似于C# version of CountDownLatch。当你想保证线程被取消时,这很有用。

+0

你的问题是我试图在我的搜索中找到的问题! – rnd 2010-08-06 00:00:05

+0

@rnd,很高兴我能帮忙! – Kiril 2010-08-06 00:10:01

1

它最终总是会导致类似这样的事情 - 尽管重要的是您要使cancel变量易变,否则工作线程可能看不到取消线程的更改。

你一定要检查东西周期性,除非你想要去中断线程(我推荐)的更激烈的路线。检查单个布尔标志不太可能是昂贵的......如果你可以在循环的每次迭代中做一个合理的工作块(足以遏制检查的成本),那很好。

如果你需要使用的等待形式进行任何等待,但是,(在工作线程),然后您可以改善的事项(如Monitor.Wait),它允许取消线程唤醒任何提前等待线索。这不会使正常操作更有效率,但它会允许线程在取消时更快地终止。

+0

C#in Depth目前正在从亚马逊前往我的路上。期待它! – rnd 2010-08-06 00:08:58

0

我会这样做。我还会将Thread.Sleep添加到循环中,以便对主线程进行控制。

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

+0

当有适当的信令实现(即Monitor或CountDownLatch)时,我不认为Thread.Sleep是必需的。 – Kiril 2010-08-05 18:57:40

+0

同意,我正在谈论一个循环内的简单变量检查。 – akonsu 2010-08-05 19:08:30

1

特别是因为它的UI触发的,我会建议只是撬动BackgroundWorker中已有的框架内,特别是因为它会很好地有进展,并在UI线程上做一些事情的发生你(这么你不必自己调用它)。

然后您可以使用CancelAsync()调用。无可否认,它与你已经在做的没有什么不同,只是在框架中完成(包括线程同步逻辑)

正如Jon所说,你仍然想要做合作取消(检查CancellationPending在你的DoWork中使用BackgroundWorker),因为'中断/中止线程'选项是你想尽可能避免的。

如果在.NET 4中,您可以使用TPL和new Cancellation support,但它又一次着重于协作取消。

+0

感谢您提供关于后台工作人员的提示,James。我会考虑转移到这个而不是我自己的实现,因为我的线程系统目前是临时测试容器。 – rnd 2010-08-06 00:01:05

1

我推荐使用.NET 4.0中引入的unified cancellation model(如果.NET 4.0是一个选项)。

这是非常有效的,并允许与Task对象和并行LINQ集成取消。