Каковы альтернативные способы приостановить и возобновить поток? - PullRequest
25 голосов
/ 19 декабря 2008

Два метода Thread.Suspend() и Thread.Resume() устарели с .NET 2.0. Зачем? Какие есть другие альтернативы и примеры?

Ответы [ 7 ]

20 голосов
/ 15 апреля 2009

Вы хотите использовать 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. Он работает так же, как и Suspend / Resume, так как AutoResetEvent позволяет «возобновить» только один поток.

11 голосов
/ 19 декабря 2008

Хорошие альтернативы работают в потоке, достигая точки, в которой он с радостью ждет. Приостановка была опасной, поскольку она могла приостановить поток, пока он удерживал блокировку на мьютексе - рецепт взаимоблокировок.

Итак, ваш поток нуждается в ManualResetEvent, который он может ожидать - в то время, когда это безопасно для него, когда он не удерживает никаких блокировок.

4 голосов
/ 19 декабря 2008

Это лучший учебник для Thread (для C #): http://www.albahari.com/threading/

Для ожидания вам нужно использовать .Join () в потоке. Это будет ждать, пока финишная дорожка не станет работой. В противном случае вам нужно будет использовать Wait / Pulse .

2 голосов
/ 15 сентября 2015

вы можете использовать ручной сброс вместо автоматического сброса:

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");

 }
 }
}
1 голос
/ 20 декабря 2008

Этот слишком длинный. Что мне нужно, это быстрый пример кода для использования. Я нашел один из обсуждения и ответил Марком Р. Доусоном в http://bytes.com/groups/net-c/458947-thread-suspend. Он объясняет опасность устаревших методов и как использовать AutoResetEvent для уведомления второго потока о продолжении обработки.

0 голосов
/ 25 ноября 2018

Причины, по которым Thread.Suspend() и Thread.Resume() устарели или удалены в .NET, в значительной степени совпадают с причинами, по которым Thread.suspend() и Thread.resume() устарели в Java. Сравнить & mdash;

  • Часто задаваемые вопросы об устаревании потока в Java (suspend "склонен к тупику"), с
  • Отметьте ответ Р.Доусона на .NET Thread.Suspend () ` (« если вы остановите поток в середине выполнения, вы можете столкнуться с тупиком и условиями гонки »).
0 голосов
/ 19 декабря 2008

Я согласен, что это отличный учебник. Основная причина, по которой Suspend () и Resume () устарели, заключается в том, что они являются довольно опасными методами. В любой момент Thread t мог делать что угодно. Что-нибудь. Представьте, что ваш поток читает файл и заблокирован. Вы приостановили свою тему. Файл остается заблокированным. То же самое касается любых других ресурсов. То же самое касается блокировки мьютекса.

...