Stoppen eines Threads, ManualResetEvent, volatile boolean oder CancellationToken

Ich habe einen Thread (STAThread) in einem Windows-Dienst, der viel Arbeit leistet. Wenn der Windows-Dienst neu gestartet wird, möchte ich diesen Thread ordnungsgemäß beenden.

Ich kenne ein paar Möglichkeiten

Ein flüchtiger Boolescher WertManualResetEventCancellationToken

Soweit ich Thread.Abort rausgefunden habe ist ein no go ...

Was ist die beste Praxis? Die Arbeit wird in einer anderen Klasse ausgeführt als der, in der der Thread gestartet wurde. Daher muss entweder ein cancelToken-Parameter in einen Konstruktor eingefügt werden oder es muss beispielsweise eine flüchtige Variable vorhanden sein. Aber ich kann einfach nicht herausfinden, was am klügsten ist.

Aktualisieren
Um es ein wenig zu verdeutlichen, habe ich ein sehr einfaches Beispiel für das, wovon ich spreche, zusammengefasst. Wie bereits erwähnt, wird dies in einem Windows-Dienst durchgeführt. Im Moment denke ich an einen flüchtigen Booleschen Wert, der in der Schleife oder einem CancellationToken aktiviert ist. Ich kann es nicht abwarten, bis die Schleife beendet ist. Dies kann, wie unten angegeben, einige Minuten dauern, sodass die Systemadministratoren des Servers dies glauben Irgendetwas stimmt nicht mit dem Dienst, wenn er neu gestartet werden muss. Ich kann die gesamte Arbeit problemlos in der Schleife ablegen, kann dies jedoch nicht mit einem Thread tun. Abbruch, es ist "böse" und außerdem ein COM Die Schnittstelle wird aufgerufen, daher ist eine kleine Bereinigung erforderlich.

Class Scheduler{
  private Thread apartmentThread;
  private Worker worker;

  void Scheduling(){
    worker = new Worker();
    apartmentThread = new Thread(Run);
    apartmentThread.SetApartmentState(ApartmentState.STA);
    apartmentThread.Start();    
  }

  private void Run() {
    while (!token.IsCancellationRequested) {
      Thread.Sleep(pollInterval * MillisecondsToSeconds);
      if (!token.IsCancellationRequested) {
        worker.DoWork();
      }
    }
  }
}

Class Worker{
  //This will take several minutes....
  public void DoWork(){
    for(int i = 0; i < 50000; i++){
      //Do some work including communication with a COM interface
      //Communication with COM interface doesn't take long
    }
  }
}

AKTUALISIEREN
Die gerade untersuchte Leistung mit einem CancellationToken, bei dem der Status isCancelled im Code "überprüft" wird, ist viel schneller als die Verwendung eines waitOne für ein ManualResetEventSlim. Ein paar schnelle Zahlen, ein 100.000.000-maliges Durchlaufen des Storno-Tokens in einer for-Schleife kostet mich ca. 500 ms, wo die WaitOne ca. 3 Sekunden. Die Leistung in diesem Szenario ist also schneller, wenn Sie das CancellationToken verwenden.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage