是否可以从拥有对象中停止线程Dispose方法?

时间:2015-07-10 19:20:18

标签: c# multithreading dispose

这是一个简单的例子:

class MyClass : IDisposable
{
    bool working;
    public MyClass()
    {
        working = true;
        Thread t = new Thread(Worker);
        t.Start();
    }
    void Worker()
    {
        while(working)
        {}
    }
    public void Dispose()
    {
        working = false;
    }
}

这样做可以吗?即使在线程仍在运行时调用Dispose()?如果没有,怎么做得更好?

2 个答案:

答案 0 :(得分:1)

除非您通过显式或通过在Dispose语句中包含MyClass实例化来调用它,否则不会调用

using

  

在线程仍在运行时,甚至会调用Dispose()吗?

可以这样称呼:

using (MyClass m = new MyClass())
{
    System.Threading.Thread.Sleep(2000);
}

一旦using块结束,它将调用您班级中的Dispose方法。

(虽然您的变量应为volatile,表示该字段可能被多个线程修改)

但需要注意的重要一点是,Dispose没有神奇之处,即使using语句也会转换为try-finally,其中Dispose被明确调用finally块。

答案 1 :(得分:1)

您不应该依赖于您的Dispose方法。

您可以使用WeakReference包装类实例。一旦引用被垃圾收集,线程就应该停止工作。

class MyClass : IDisposable
{
    class CancellationSignal
    {
        WeakReference _reference;
        public bool IsWorking { get { return _working && _reference.IsAlive; } }
        volatile bool _working;

        public CancellationSignal(WeakReference reference)
        {
            if (reference == null) throw new ArgumentNullException("reference");
            _reference = reference;
        }

        public void Signal()
        {
            _working = false;
        }

    }

    CancellationSignal _cancellationSignal;

    public MyClass()
    {
        _cancellationSignal = new CancellationSignal(new WeakReference(this));
        Thread t = new Thread(Worker);
        t.Start(_cancellationSignal);
    }

    static void Worker(object state)
    {
        var s = (CancellationSignal)state;
        while (s.IsWorking)
        {
            //...
        }
    }

    public void Dispose()
    {
        _cancellationSignal.Signal();
    }
}

我个人更喜欢避免使用终结器,但我仍然不得不说另一个解决方案是在终结器中调用Signal(然后你可以删除WeakReference个东西):

 ~MyClass()
 {
    _cancellationSignal.Signal();
 }

请注意_working被声明为volatile。您也可以使用ManualResetEventSlim甚至CancellationToken代替。

在两种方法(WeakReference和终结器)中,您必须避免将this引用传递给Thread(因为它会阻止您的类实例被垃圾回收)因此我添加了CancellationSignalWorker标记为静态。