永远不会使用Thread.Suspend
。它的主要问题是99%的时间你不知道当你挂起它时该线程在做什么。如果该线程持有一个锁,则可以更容易进入死锁状态等。请记住,您正在调用的代码可能会在幕后获取/释放锁。 Win32有一个类似的API:SuspendThread
和ResumeThread
。为SuspendThread
下面的文档给API的危险的一个很好的总结:
http://msdn.microsoft.com/en-us/library/ms686345(VS.85).aspx
此功能主要是用来调试程序的使用。它不打算用于线程同步。在拥有同步对象(如互斥锁或临界区)的线程上调用SuspendThread,如果调用线程试图获取暂停线程拥有的同步对象,则可能导致死锁。为了避免这种情况,应用程序中不是调试器的线程应该发信号通知其他线程自行挂起。目标线程必须设计为监视此信号并进行适当的响应。
无限期暂停线程的正确方法是使用ManualResetEvent
。线程很可能循环,执行一些工作。暂停线程,最简单的方法就是让线程“检查”了事件的每一次迭代中,像这样:
while (true)
{
_suspendEvent.WaitOne(Timeout.Infinite);
// Do some work...
}
您指定一个无限超时,所以当没有信号的情况下,该线程将无限期阻塞,直到该事件将在该点停止的地方恢复。
您可以创建事件,像这样:
ManualResetEvent _suspendEvent = new ManualResetEvent(true);
的true
参数通知事件处于信号态开出。
当要暂停线程,你执行以下操作:
_suspendEvent.Reset();
并恢复线程:
_suspendEvent.Set();
您可以使用类似的机制通知线程退出,等待两个事件,检测哪个事件被发送。
只是为了好玩,我会提供一个完整的例子:
public class Worker
{
ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
ManualResetEvent _pauseEvent = new ManualResetEvent(true);
Thread _thread;
public Worker() { }
public void Start()
{
_thread = new Thread(DoWork);
_thread.Start();
}
public void Pause()
{
_pauseEvent.Reset();
}
public void Resume()
{
_pauseEvent.Set();
}
public void Stop()
{
// Signal the shutdown event
_shutdownEvent.Set();
// Make sure to resume any paused threads
_pauseEvent.Set();
// Wait for the thread to exit
_thread.Join();
}
public void DoWork()
{
while (true)
{
_pauseEvent.WaitOne(Timeout.Infinite);
if (_shutdownEvent.WaitOne(0))
break;
// Do the work here..
}
}
}
我得去和阅读电子书。我从来没有遇到挂起/恢复自己的问题。 – 2008-09-27 03:02:27