【问题标题】:C#: Properly freeing threadC#:正确释放线程
【发布时间】:2009-05-07 23:43:32
【问题描述】:

我有一个抽象类,它在其构造函数中生成一个无限循环线程。确保在使用完类后中止该线程的最佳方法是什么?

我应该实现 IDisposable 并简单地使用这个吗?

public void Dispose()
{
    this.myThread.Abort();
}

我读到 Abort() 是邪恶的。我是否应该让 Dispose() 设置一个私有 bool 标志,线程检查其是否为 true 以退出其循环?

public void Dispose()
{
    this.abort = true;
}

//在线程的循环中...

if (this.abort)
{
    break;
}

改用 BackgroundWorker 类?

【问题讨论】:

    标签: c# multithreading


    【解决方案1】:

    我想扩展“lc”提供的答案(否则很好)。

    要使用他的方法,您还需要将布尔标志标记为“易失性”。这将引入一个“内存屏障”,它将确保每次您的后台线程读取变量时,它都会从内存(而不是寄存器)中获取它,并且当变量被写入时,数据会在 CPU 缓存之间传输.

    【讨论】:

      【解决方案2】:

      不要使用无限循环,而是使用可由主类设置的布尔标志作为循环条件。完成后,设置标志以便循环可以正常退出。如果你实现了IDisposable,设置标志并等待线程终止后再返回。

      您可以实现一个可取消的BackgroundWorker 类,但本质上它会完成同样的事情。

      如果你真的想要,你可以在发送信号后给它一个时间窗口来完成它自己。如果它没有终止,您可以像 Windows 在关机时一样中止线程。

      我认为Thread.Abort 被认为是“邪恶”的原因是它使事物处于未定义状态。然而,与杀死整个进程不同的是,剩余的线程会继续运行并且可能会遇到问题。

      【讨论】:

      • C# 是否不需要为此类标志设置任何类型的内存屏障?
      • 确实如此。您需要使用“volatile”关键字。请参阅下面的帖子。
      • 在实践中,即使没有 volatile(至少在 x86 和 x64 上),您最终也会看到标志值——这可能需要一些时间(几毫秒),但您会看到它。不过理论上,Scott 是对的,实际上应该在这里使用 volatile。
      【解决方案3】:

      我建议使用 BackgroundWorker 方法。实施起来相对简单,而且清理得很好。

      【讨论】:

        猜你喜欢
        • 2017-12-21
        • 1970-01-01
        • 2011-09-13
        • 2014-11-05
        • 1970-01-01
        • 2019-05-27
        • 2011-05-07
        • 2016-06-24
        • 2014-12-17
        相关资源
        最近更新 更多