【问题标题】:Efficient Cancel Event Implementation for Number Crunching Threads?数字处理线程的有效取消事件实现?
【发布时间】:2010-08-05 18:48:28
【问题描述】:

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

目前,我只是使用从我的 UI 线程触发的取消事件,该事件随后在数字处理线程上调用“onCancel”函数。该取消函数将变量设置为“true”,紧缩循环会定期检查该变量,例如

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 取消),但我仍然希望尽可能优化这种 crunch 方法。任何可以更有效地完成此操作的示例都会很高兴看到。

【问题讨论】:

  • 在非常紧凑的循环中,我通过仅检查每 100 或 1000 次迭代而不是每一次迭代来进行优化。但你必须检查。

标签: c# multithreading events


【解决方案1】:

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

我还建议,当您取消线程时,您可以使用类似于C# version of CountDownLatch 的方法来等待所有线程都取消。当您想保证线程被取消时,它很有用。

【讨论】:

  • 你的问题是我试图在搜索中找到的问题!
【解决方案2】:

它最终总是会导致这样的结果 - 尽管让 cancel 变量变为 volatile 很重要,否则工作线程可能看不到取消线程的更改。

你必须定期检查一些东西,除非你想采取更激烈的方式来中断线程(我推荐)。检查单个布尔标志的成本可能不太高...如果您可以在循环的每次迭代中进行合理的工作(足以使检查的成本相形见绌),那就没问题了。

如果您需要执行任何等待,但是(在工作线程中),那么您可以通过使用允许的等待形式(例如 Monitor.Wait)来改善问题取消线程以提前唤醒任何等待的线程。这不会提高正常操作的效率,但会允许线程在取消时更快地终止。

【讨论】:

  • C# in Depth 目前正在一辆卡车上,正从亚马逊驶来。期待!
【解决方案3】:

特别是因为它是由 UI 触发的,我建议只利用框架中已经存在的 BackgroundWorker,特别是因为它会很好地为您在 UI 线程上发生进度和完成事件(所以您不会必须自己调用它)。

然后您可以使用 CancelAsync() 调用。诚然,它与您已经在做的事情并没有太大的不同,只是已经在框架中完成了(并且包括线程同步逻辑)

正如 Jon 所提到的,您仍然希望进行协作取消(检查 DoWork 中的 CancellationPending 以使用 BackgroundWorker),因为如果可能的话,您希望避免使用“中断/中止线程”选项。

如果在 .NET 4 中,您可以使用 TPL 和 new Cancellation support,但它同样侧重于协作取消。

【讨论】:

  • 感谢有关后台工作人员 James 的提示。我会考虑转移到这个而不是我自己的实现,因为我的线程系统目前是一个临时测试容器。
【解决方案4】:

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

它非常高效,并且允许与 Task 对象和并行 LINQ 集成取消。

【讨论】:

    【解决方案5】:

    我也会这样做。我还会将 Thread.Sleep 添加到循环中以将控制权交给主线程。

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

    【讨论】:

    • 我不认为 Thread.Sleep 在实现了适当的信号(即 Monitor 或 CountDownLatch)时是必要的。
    • 同意,我说的是循环内的简单变量检查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多