Ma principale préoccupation concerne l'indicateur booléen ... est-il sûr de l'utiliser sans aucune synchronisation? J'ai lu à plusieurs endroits que c'est atomique (y compris la documentation).
class MyTask
{
private ManualResetEvent startSignal;
private CountDownLatch latch;
private bool running;
MyTask(CountDownLatch latch)
{
running = false;
this.latch = latch;
startSignal = new ManualResetEvent(false);
}
// A method which runs in a thread
public void Run()
{
startSignal.WaitOne();
while(running)
{
startSignal.WaitOne();
//... some code
}
latch.Signal();
}
public void Stop()
{
running = false;
startSignal.Set();
}
public void Start()
{
running = true;
startSignal.Set();
}
public void Pause()
{
startSignal.Reset();
}
public void Resume()
{
startSignal.Set();
}
}
Est-ce un moyen sûr de concevoir une tâche de cette manière? Des suggestions, des améliorations, des commentaires?
Remarque: j'ai écrit ma classe CountDownLatch
personnalisée au cas où vous vous demanderiez d'où je l'obtiens.
Mise à jour:
Voici aussi mon CountDownLatch:
public class CountDownLatch
{
private volatile int m_remain;
private EventWaitHandle m_event;
public CountDownLatch (int count)
{
if (count < 0)
throw new ArgumentOutOfRangeException();
m_remain = count;
m_event = new ManualResetEvent(false);
if (m_remain == 0)
{
m_event.Set();
}
}
public void Signal()
{
// The last thread to signal also sets the event.
if (Interlocked.Decrement(ref m_remain) == 0)
m_event.Set();
}
public void Wait()
{
m_event.WaitOne();
}
}
Vous feriez mieux de le marquer volatile
cependant:
Le mot clé volatile indique qu'un champ peut être modifié par plusieurs threads s'exécutant simultanément. Les champs déclarés volatils ne sont pas soumis aux optimisations du compilateur qui supposent l'accès par un seul thread. Cela garantit que la valeur la plus à jour est présente dans le champ à tout moment.
Mais je changerais votre boucle:
startSignal.WaitOne();
while(running)
{
//... some code
startSignal.WaitOne();
}
Tel qu'il est dans votre message, le 'certain code' peut s'exécuter lorsque le thread est arrêté (c'est-à-dire lorsque Stop est appelé), ce qui est inattendu et peut être même incorrect.
Les booléens sont atomiques en C #, cependant, si vous voulez le modifier dans un thread et le lire dans un autre, vous devrez au moins le marquer comme volatile. Sinon, le thread de lecture ne peut le lire qu'une seule fois dans un registre.
Les booléens sont atomiques en C #: http://msdn.Microsoft.com/en-us/library/aa691278 (VS.71) .aspx
BTW, je viens de remarquer cette partie du code:
// A method which runs in a thread
public void Run()
{
startSignal.WaitOne();
while(running)
{
startSignal.WaitOne();
//... some code
}
latch.Signal();
}
Vous devrez débloquer le thread de travail deux fois en utilisant "startSignal.Set ()" pour que le code du bloc while s'exécute.
Est-ce délibéré?