N'utilisez jamais d' Thread.Suspend
. Le principal problème c'est que 99% du temps, vous ne pouvez pas savoir ce que le thread est en train de faire lorsque vous le suspendre. Si ce thread est verrouillé, vous rendre plus facile à obtenir dans une situation de blocage, etc. Gardez à l'esprit que le code que vous appelez peut-être l'acquisition/suppression des verrous derrière les coulisses. Win32 dispose d'une API similaire: SuspendThread
et ResumeThread
. Les documents suivants pour SuspendThread
donne un bon résumé des dangers de l'API:
http://msdn.microsoft.com/en-us/library/ms686345(SV.85).aspx
Cette fonction est principalement conçu pour une utilisation par les débogueurs. Il n'est pas destiné à être utilisé pour la synchronisation des threads. L'appel de SuspendThread sur un thread qui possède un objet de synchronisation, comme un mutex ou de la section critique, peut conduire à un blocage si le thread appelant essaie d'obtenir un objet de synchronisation détenue par un thread suspendue. Pour éviter cette situation, un thread dans une application qui n'est pas un débogueur doit le signal de l'autre thread de suspendre lui-même. Le thread cible doit être conçu de manière à regarder pour ce signal et de réagir de façon appropriée.
La bonne façon de le suspendre à un fil indéfiniment est d'utiliser un ManualResetEvent
. Le fil est le plus susceptible de bouclage, de l'exécution de certains travaux. Le moyen le plus facile de suspendre le fil est d'avoir la discussion "vérifier" l'événement chaque itération, comme suit:
while (true)
{
_suspendEvent.WaitOne(Timeout.Infinite);
// Do some work...
}
Vous spécifiez un délai d'attente infinie ainsi, lorsque l'événement n'est pas signalé, le thread va bloquer indéfiniment, jusqu'à ce que l'événement est signalé à quel point le thread va reprendre là où il l'avait laissé.
Vous devez créer l'événement comme suit:
ManualResetEvent _suspendEvent = new ManualResetEvent(true);
L' true
paramètre indique à l'événement pour commencer dans l'état signalé.
Lorsque vous souhaitez interrompre le thread, vous effectuez les opérations suivantes:
_suspendEvent.Reset();
Et pour reprendre le fil:
_suspendEvent.Set();
Vous pouvez utiliser un mécanisme similaire pour signaler le fil de sortie et d'attente sur les deux événements, la détection de l'événement qui a été signalée.
Juste pour le plaisir, je vais vous donner un exemple complet:
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..
}
}
}