从 .NET 2.0 开始Thread.Suspend()
,这两种方法都已过时。Thread.Resume()
为什么?还有哪些其他选择和示例?
8 回答
您需要使用 AutoResetEvent EventWaitHandle。
假设你想做这样的事情(注意:不要这样做!):
private Thread myThread;
private void WorkerThread()
{
myThread = Thread.CurrentThread;
while (true)
{
myThread.Suspend();
//Do work.
}
}
public void StartWorking()
{
myThread.Resume();
}
正如其他人所说,这是一个坏主意。尽管仅在其自己的线程上使用 Suspend 相对安全,但您永远无法确定您是否在线程实际挂起时调用 Resume。所以 Suspend 和 Resume 已经过时了。
相反,您想使用 AutoResetEvent:
private EventWaitHandle wh = new AutoResetEvent();
private void WorkerThread()
{
while(true)
{
wh.WaitOne();
//Do work.
}
}
public void StartWorking()
{
wh.Set();
}
工作线程将在等待句柄上等待,直到另一个线程调用 StartWorking。它的工作原理与暂停/恢复非常相似,因为 AutoResetEvent 只允许“恢复”一个线程。
好的替代方案都是通过线程达到它乐于等待的点来工作的。挂起是危险的,因为它可能会在线程持有互斥锁时挂起线程 - 这是死锁的秘诀。
因此,您的线程需要的是一个可以等待的 ManualResetEvent - 在它可以安全地这样做的时候,当它没有持有任何锁时。
这是有史以来最好的 Thread 教程(用于 C#):http ://www.albahari.com/threading/
对于等待,您需要在线程上使用 .Join() 。这将等到胎面完成工作。否则,您将需要使用Wait/Pulse。
您可以使用 ManualReset 而不是 AutoReset:
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();
Console.WriteLine("Thread started running");
}
public void Pause()
{
_pauseEvent.Reset();
Console.WriteLine("Thread paused");
}
public void Resume()
{
_pauseEvent.Set();
Console.WriteLine("Thread resuming ");
}
public void Stop()
{
// Signal the shutdown event
_shutdownEvent.Set();
Console.WriteLine("Thread Stopped ");
// 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..
Console.WriteLine("Thread is running");
}
}
}
那个太长了 我需要的是一个快速的示例代码来使用。我从讨论中找到了一个并由 Mark R. Dawson 在http://bytes.com/groups/net-c/458947-thread-suspend回答。它解释了过时方法的危险以及如何使用 AutoResetEvent 通知第二个线程继续处理。
我同意这是一个很棒的教程。Suspend() 和 Resume() 过时的主要原因是它们是非常危险的方法。在任何时候 Thread t 都可以做任何事情。任何事物。想象一下,您的线程正在读取一个文件并对其进行了锁定。你暂停你的线程。文件保持锁定状态。任何其他资源也是如此。互斥锁上的锁也是如此。
.NET 中过时或删除的原因与Thread.Suspend()
Java中过时和过时的原因基本相同。相比-Thread.Resume()
Thread.suspend()
Thread.resume()
- Java 的线程原语弃用常见问题解答(
suspend
“天生容易死锁”),与 - Mark R. Dawson对 .NET 的 Thread.Suspend()` 的回答(“如果您在执行过程中停止线程,您可能会遇到死锁和竞争条件”)。
解决方案:只有当另一个线程自己挂起时,才让一个线程恢复另一个线程。因此,第一个线程仅在另一个线程暂停自身(即其 ThreadState = Suspended)时才恢复另一个线程,从而使自己准备好恢复。这似乎安全无瑕。
或者,我不了解 .Net 线程吗?