2015-07-10 68 views
1

下面是一个简单的例子:可以从拥有的对象中停止线程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()?如果没有,如何更好地做到这一点?

+0

对我来说似乎很好。除非你想至少让'working'变量'volatile'。否则,即使在处理“MyClass”后,实际上您的线程也可能永远不会结束。 – sstan

回答

1

Dispose将不会被调用,除非您明确地或通过在using声明中封装MyClass实例。

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

它可以这样调用:

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

所以一旦using块结束时,它会在你的类调用Dispose方法。

(虽然你的变量应该是volatile,表明该领域可能会被多个线程修改)

但要注意的最重要的事情是,有没有神奇的事情有关Dispose,连using声明转换为try-finally,其中Disposefinally块中被明确调用。

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是声明为不稳定。您也可以使用ManualResetEventSlim或甚至CancellationToken

在这两种方法(WeakReference和终结),你必须避免将this参考主题(因为它会阻止垃圾回收你的类的实例),因此我添加了一个CancellationSignal类和标注Worker为静态。

+0

我将不得不看到你正在考虑的'WeakReference'想法的代码。但我怀疑这两种方法和终结器方法都行不通,因为在委托给'线程的'Worker'方法时,它隐式地将一个硬引用传递给'this'(MyClass'实例)。所以,除非'Dispose'被明确调用,否则我认为该线程实际上会阻止'MyClass'实例进行垃圾收集。还没有尝试过。 – sstan

+0

@sstan,我添加了代码 – Vlad

+0

我建议让弱引用指定一个公开暴露的façade对象,并指定该对象的服务只保证运行,而强制引用存在于该façade。此外,我建议让“主要”对象提供一个可以从外观的终结器调用的“微调”方法,如果它正在等待某个东西,它可以用来中断主线程。在没有获取锁的情况下无法脉冲显示器会使事情变得有点恶心(即使在设置标志后,终结器方法应该能够立即返回... – supercat

相关问题