web-dev-qa-db-fra.com

Quels sont les moyens alternatifs de suspendre et de reprendre un fil?

Les deux méthodes Thread.Suspend() et Thread.Resume() sont obsolètes depuis .NET 2.0. Pourquoi? Quelles sont les autres alternatives et des exemples?

23
David.Chu.ca

Vous voudrez utiliser un AutoResetEvent EventWaitHandle.

Dites que vous voulez faire quelque chose comme ça (NOTE: ne faites pas ça!): 

private Thread myThread;

private void WorkerThread() 
{
    myThread = Thread.CurrentThread;
    while (true)
    {
        myThread.Suspend();
        //Do work.
    }
}

public void StartWorking() 
{
    myThread.Resume();
}

Comme d'autres l'ont dit, c'est une mauvaise idée. Même si l'utilisation de Suspend sur son propre thread est relativement sûre, vous ne pouvez jamais savoir si vous appelez Reprendre lorsque le thread est réellement suspendu. Donc, suspendre et reprendre ont été obsolètes. 

Au lieu de cela, vous voulez utiliser un AutoResetEvent:

private EventWaitHandle wh = new AutoResetEvent();

private void WorkerThread() 
{
    while(true) 
    {
        wh.WaitOne();
        //Do work.
    }
}

public void StartWorking()
{
    wh.Set();
}

Le thread de travail attendra la poignée d'attente jusqu'à ce qu'un autre thread appelle StartWorking. Cela fonctionne de la même manière que Suspend/Resume, dans la mesure où AutoResetEvent ne permet de "reprendre" qu'un seul thread. 

20
Darcy Casselman

Les bonnes alternatives fonctionnent toutes par le fil jusqu'à atteindre un point où il est heureux d'attendre. Suspendre était dangereux car il pouvait suspendre le fil alors qu'il tenait un verrou sur un mutex - une recette pour des impasses.

Donc ce dont votre thread a besoin, c'est d'un ManualResetEvent qu'il peut attendre - à un moment où il peut le faire en toute sécurité, quand il ne détient aucun verrou.

11
Daniel Earwicker

C’est le meilleur tutoriel à ce jour pour Thread (pour C #): http://www.albahari.com/threading/

Pour attendre, vous devez utiliser .Join () sur le fil. Cela attendra que la finition de la bande de roulement soit terminée. Sinon, vous devrez utiliser Wait/Pulse .

4
Patrick Desjardins

vous pouvez utiliser ManualReset au lieu de 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");

 }
 }
}
1
Luke

Celui-là est trop long. Ce dont j'ai besoin, c'est d'un exemple de code rapide à utiliser. J'en ai trouvé un dans la discussion et Mark R. Dawson a répondu à http://bytes.com/groups/net-c/458947-thread-suspend . Il explique le danger des méthodes obsolètes et explique comment utiliser AutoResetEvent pour informer le second thread de poursuivre le traitement.

1
David.Chu.ca

Les raisons pour lesquelles Thread.Suspend() et Thread.Resume() sont obsolètes ou supprimées dans .NET sont essentiellement les mêmes que celles pour lesquelles Thread.suspend() et Thread.resume() sont obsolètes en Java. Comparer-

0
Peter O.

Je suis d'accord que c'est un excellent tutoriel. La principale raison pour laquelle Suspend () et Resume () sont obsolètes, c’est parce que ce sont des méthodes assez dangereuses. À tout moment, Thread t pouvait faire n'importe quoi. N'importe quoi. Imaginez que votre sujet lit un fichier et qu’il est verrouillé. Vous suspendez votre fil. Le fichier reste verrouillé. Il en va de même pour toutes les autres ressources. Même chose pour un verrou sur un mutex.

0
Szymon Rozga