Никогда, никогда не используйте 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..
}
}
}
27.09.2008