2010-12-03 2 views
1

Disons que nous avons un programme suivant où, dans sa méthode Start, il délègue une tâche longue à un autre thread. Lorsque la méthode Stop est appelée, je dois m'assurer que le thread de travail termine l'exécution de la tâche en cours et ne la laisse pas au milieu. S'il a déjà terminé la tâche et est en état de veille, il peut alors s'arrêter immédiatement.Attendre que le thread principal s'arrête jusqu'à ce qu'une tâche soit traitée par un thread asynchrone

S'il vous plaît me guider sur la façon dont je devrais le faire.

static int itemsProcessed = 0; 
    static Thread worker; 
    static void Start() 
    { 
     var ts = new ThreadStart(Run); 
     worker = new Thread(ts); 
     worker.Start(); 
    } 

    static void Stop() 
    { 
     //wait until the 'worker' completes processing the current item. 
     Console.WriteLine("{0} Items Processed", itemsProcessed); 
    } 

    static void Run(object state) 
    { 
     while (true) 
     { 
      ALongRunningTask(); 
      itemsProcessed++; 
      Thread.Sleep(1000); 
     } 
    } 

Répondre

1

une façon de le faire est d'utiliser une variable volatile pour communiquer betweej les deux fils. Pour ce faire, créez un "volatile bool isRunning;". Dans Start, définissez la valeur sur true, puis dans Run, déplacez votre boucle while sur "while (isRunning)". Dans stop, définissez isRunning égal à false, puis appelez worker.Join(). Cela entraînera la sortie de votre méthode d'exécution à la fin du traitement de l'élément en cours et Join attendra jusqu'à ce que le thread se termine.

La dernière chose à faire est d'accéder à des éléments traités de manière thread-safe. Dans le code actuel, il n'y a aucun moyen de savoir si Stop voit la valeur la plus à jour de itemsProcessed car il a été modifié à partir d'un autre thread. Une option serait de créer un verrou pour itemsProcessed et de maintenir le verrou à l'intérieur de Run, et d'acquérir le verrou avant l'instruction WriteLine dans Stop.

1

En supposant que vous voulez toujours le fil de travail de longue course dans son ensemble pour terminer, vous pouvez simplement attendre jusqu'à ce que le fil se fait en appelant Thread.Join(); Si vous voulez terminer votre travail avec élégance, vous devez passer un certain type de message, dans le cas le plus simple, il pourrait s'agir d'un simple booléen - dans votre cas, il semble y avoir un seul fil, donc il peut être une variable statique (en simplifiant ici autant que possible)

static volatile bool processing = true; 
static void Stop() 
{ 
    processing = false; 
    //wait until the 'worker' completes processing the current item. 
    worker.Join(); 
    Console.WriteLine("{0} Items Processed", itemsProcessed); 
} 


static void Run(object state) 
{ 
    while (proccessing) 
    { 
     ALongRunningTask(); 
     itemsProcessed++; 
    } 
} 
+0

Cela doit être traité pour être volatile, sinon l'autre thread peut ne jamais remarquer que la valeur est modifiée. Vous pouvez également utiliser la méthode worker.Join au lieu de la boucle de veille. –

+0

les deux déclarations correctes, je reçois un prototypage bâclé. J'ai édité mon post – BrokenGlass

Questions connexes