For example, there are several almost identical flows that can last indefinitely.

initialization:

ParameterizedThreadStart pts = new ParameterizedThreadStart(runMethod); Thread t = new Thread(pts); t.Start(values); 

flow:

  void run(object p) { // нужен поток, который повторяет одно и то же с некоторой переодичностью, поэтому так: while(true) { // что-то делаем doAnything(p); Thread.Sleep(60000); } } 

The question is how to adequately interrupt them? It would be great if you could interrupt them while they were sleeping or at least after doAnything ();

you can do something like in the main thread

  Thread t = new Thread(pts); t.Start(values); ... t.Abort(); 

but I am not sure that some important operation will not be interrupted in the stream - loading / deleting / processing a file or a transaction will not open

  • one
    It seems that this question has already been asked several times already - but those times were not so “clean”, they were mixed with other problems. - Pavel Mayorov
  • one
    Possible duplicate of the question: How to implement stopping a thread before launching its new instance? - andreycha
  • @andreycha I understand that there you answered about the same thing as me - but the questions are different! Here the question is more general. - Pavel Mayorov
  • @andreycha streams need to be stopped not only before starting a new instance, but, for example, before stopping the service. - Pavel Mayorov
  • Maybe not in the subject, but I do not understand why this is all, if in the yard 2016 C # 6.0, .Net 4.6 and there is a TPL and async / await? - Bulson

2 answers 2

Most beautifully, this is done through the CancellationToken mechanism. This mechanism is specifically designed to transmit stop and cancel messages between threads:

 void run(object p) { var ct = (CancellationToken)p; do { // что-то делаем doAnything(p); } while (!ct.IsCancellationRequested && !ct.WaitHandle.WaitOne(60000)); } 

Here I use event wait as an interrupted alternative to Thread.Sleep . If waiting is successful, it means that the flow should be stopped. If unsuccessful (timeout waiting) - then you can continue to work.

Before waiting, I check IsCancellationRequested to not create a kernel event when this is not required.

Creating such a stream:

 using (var cts = new CancellationTokenSource()) { new Thread(run).Start(cts.Token); ... cts.Cancel(); } 

Also, instead of a stream, you can use a task ( Task.Run ). In this case, it is better to use Task.Delay , this will make it possible to do without the kernel objects:

 async Task run(CancellationToken ct) { do { // что-то делаем doAnything(p); await Task.Delay(60000, ct); } while (!ct.IsCancellationRequested); } Task.Run(() => run(cts.Token)); 

A bonus to using CancellationToken is the ability to send ct further to doAnything - so you can finely choose at what points the interruption of processing is acceptable.

If you use the asynchronous version, then almost all the asynchronous functions of the standard library can also accept CancellationToken , which allows you to safely interrupt any long operation if you wish.


In older runtimes where the CancellationToken mechanism is not present, ManualResetEvent can be used for the same purpose. The principle is the same - instead of calling Thread.Sleep wait on the event and check the result.

  • With the presence of lambda in the language, the need to transfer the object to the stream and the cast in the CancellationToken is not so great in theory. Although your code is declared as a code for the old version of the language, so ... - VladD
  • @VladD honestly, I see no reason to make a lambda for any reason - Pavel Mayorov
  • Well, for type safety, I wouldn't regret lambda. But this is a matter of personal preference. - VladD

There is a more detailed answer here and here.

  1. The easiest option is to create a boolean variable that tracks the request to terminate the thread. This option does not allow to interrupt Thread.Sleep .

     boolean volatile isRunning = true; void run(object p) { while(true) { if (!isRunning) break; // exit if not running doAnything(p); Thread.Sleep(60000); } } 
  2. Another option is to use the CancellationTokenSource . Suitable since .net 4

  • one
    bool variable will not allow Thread.Sleep to terminate. - VladD
  • one
    Yes, right, corrected, I wanted to describe all the possible options, starting with the most primitive ones, but I saw that the answer was already published in detail while I wrote the first one. - Evgenii Izhboldin