我有一个在线程中使用非托管资源的类,它也可以在不使用时进入休眠状态。我正在为它实现dispose,请参阅下面的示例代码(注意它是我的应用程序的一个愚蠢的版本)。我添加了(TheThread.IsAlive());在DestroySomeUnmangedResouces()执行之前,dispos可以设置为true。我不认为我所做的是正确的,所以如果有人能提出更好的模型,我将不胜感激。
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
//managed
}
//unmanged
_stopTheThread = true;
startTheThreadEvent.Set();
while(TheThread.IsAlive());
}
disposed = true;
}
private void TheThread()
{
while (!_stopTheThread)
{
if (state == State.Stopped)
{
// wait till a start occurs
startTheThreadEvent.WaitOne();
}
switch (state)
{
case Init:
CreateSomeUnmangedResouces();
break;
case Run:
DoStuffWithUnmangedResouces();
break;
case Stop:
DestroySomeUnmangedResouces();
break;
} // switch
}
// Release unmanaged resources when component is disposed
DestroySomeUnmangedResouces();
}
答案 0 :(得分:2)
您似乎想等到工作线程退出。为此,您可以简单地使用Thread.Join(),它将阻塞直到您的线程退出。
目前,您正在等待线程上占用100%的CPU,因为如果工作线程仍处于活动状态,则会进行轮询。资源消耗较少的变体是一种限制性轮询,您可以在支票之间至少休息一次(15ms)。
但是迄今为止最好的方法是等待一个同步原语,当条件变为真时,该原语会发出信号并唤醒你的线程。因此,Thead.Join是要走的路。
答案 1 :(得分:1)
private readonly ManualResetEvent _stopEvent = new ManualResetEvent(false);
private readonly ManualResetEvent _threadStoppedEvent = new ManualResetEvent(false);
private bool disposed;
private int checkInterval = 10;//ms
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
//managed
}
//unmanged
_stopEvent.Set();
_threadStoppedEvent.WaitOne();
}
disposed = true;
}
private void TheThread()
{
CreateSomeUnmangedResouces();
while (!_stopEvent.WaitOne(checkInterval))
{
DoStuffWithUnmangedResouces();
}
DestroySomeUnmangedResouces();
_threadStoppedEvent.Set();
}
如果您的主题不是背景,您可以使用Thread.Join()而不是_threadStoppedEvent
答案 2 :(得分:1)
调用者调用dispose应该删除线程 - 最好的方法是按照Alois的建议调用Join。一旦线程加入,那么你可以销毁现在将在调用者线程上发生的非托管资源。 E.g:
protected virtual void
Dispose
(bool disposing)
{
if (!disposed)
{
if (disposing)
{
if(TheThread != null)
{
// send a signal to stop the thread.
_stopTheThread = true;
startTheThreadEvent.Set();
// Join the thread - we could timeout here but it should be the
// responsibility of the thread owner to ensure it exits
// If this is hanging then the owning object hasn't terminated
// its thread
TheThread.Join();
TheThread = null;
}
}
// Now deal with unmanaged resources!
DestroySomeUnmangedResouces();
}
disposed = true;
}
这种方法的一个缺点是我们假设线程最终会退出。它可以挂起,意味着停止线程的信号是不够的。 Join有overloads,其中包括超时,可用于防止挂起调用线程(请参阅上面的代码示例中的注释)。
答案 3 :(得分:0)
如果正在运行的线程持有对象的直接或间接强引用,则此引用将阻止该对象符合垃圾回收的条件。因此,没有任何理由在这样的物体上设置终结器。
但是,如果该线程仅在引用某个其他特定对象由除线程之外时才具有相关性,则该线程可能有用{{ 1}}到另一个对象,如果其他对象超出范围,则自行关闭。这种关闭可以通过让线程周期性地检查WeakReference
的{{1}}属性,或者让另一个对象包含一个表示线程关闭的终结器来完成。虽然定期轮询这些东西在某种意义上是icky,并且使用终结器可以在一定程度上加快线程的关闭,我认为轮询可能仍然更好。尽管终结器可以通知线程它应该做某事,并且有时这样做可能是合适的,但一般来说,对象最终确定的事实意味着没有人过分担心及时清理。再加几秒钟'在线程关闭之前的延迟可能不会伤害任何事情。