这是一个简单的例子:
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 :(得分: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(因为它会阻止您的类实例被垃圾回收)因此我添加了CancellationSignal
将Worker
标记为静态。