永远不要使用
Thread.Suspend。它的主要问题是,在挂起线程时,有99%的时间您不知道该线程在做什么。如果该线程持有锁,则可以更容易陷入死锁等情况。请记住,您正在调用的代码可能正在幕后获取/释放锁。Win32具有类似的API:
SuspendThread和
ResumeThread。以下文档为
SuspendThreadAPI的危害提供了很好的摘要:
http://msdn.microsoft.com/zh-
cn/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.. } }}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)