On the form (WinForms) there is a button, by clicking on which a separate stream starts. If, during its execution, once again to press this button, then its work should be completed. How to correctly implement this simple logic in this code?

private void button1_Click(object sender, EventArgs e) { Button ClickedButton = (Button)sender; //класс "singleton" в котором выполняется поток (для удобства) FormAssistent.FormAssistentWorker worker = FormAssistent.FormAssistentWorker.getInstance(); //если поток еще не завершился, вызываем Abort()...так правильно? if (!worker.isComplete()) { worker.Abort(); return; } //а этот метод стартует поток (Parameters здесь опущен для краткости) worker.Arrange(Parameters); } //класс "FormAssistentWorker" - singleton, обертка над потоком public class FormAssistentWorker { //singleton private static FormAssistentWorker instance; //Поток для выполнения расстановки форм private Thread FormAssistentThread; private FormAssistentWorker() { FormAssistentThread = getFormAssistentThread(); } public static FormAssistentWorker getInstance() { if (instance == null) instance = new FormAssistentWorker(); return instance; } public void Arrange(ArrangeParameters param) { Thread workThread = getFormAssistentThread(); //вот тут возникает System.Threading.ThreadStateException //так как поток в состоянии "Aborted". Как это исправить? //Нужно обрабатывать это состояние в getFormAssistentThread()? workThread.Start(param); } public bool isComplete() { return !(FormAssistentThread.IsAlive); } public void Abort() { if (FormAssistentThread != null) FormAssistentThread.Abort(); } private Thread getFormAssistentThread() { if (FormAssistentThread == null) { FormAssistentThread = new Thread(new ParameterizedThreadStart(Work)); } if (FormAssistentThread.ThreadState == System.Threading.ThreadState.Running) { FormAssistentThread.Join(); } if (FormAssistentThread.ThreadState == System.Threading.ThreadState.Stopped) { FormAssistentThread.Abort(); FormAssistentThread = new Thread(new ParameterizedThreadStart(Work)); } return FormAssistentThread; } private void Work(object ArrangeParam) { ArrangeParameters parameters = (ArrangeParameters)ArrangeParam; parameters.formAssistent.Arrange(parameters); } } 

    2 answers 2

    I can say how to do this with the Task and CancellationToken threads

      CancellationTokenSource cancelTokenSource = new CancellationTokenSource(); CancellationToken token = cancelTokenSource.Token; Task task = new Task(() => { //Work if (token.IsCancellationRequested) { //cancel return; } //Work }); task.Start(); //повторное нажатие кнопки вызывает cancelTokenSource.Cancel(); 
    • Yes, in my case it was possible to apply the CancellationTokenSource classes. Everything works, thank you! - Sergey Ser

    You are doing wrong. Thread.Abort is a very dangerous function, it should not be used. To complete a task, the code for this task must cooperate , that is, complete itself when asked to do so.

    The simplest solution is with a volatile bool type flag, but it is better to use the CancellationToken specially designed for such purposes.