How to stop a task immediately.

tfsss 41 Reputation points
2022-07-21T06:59:52.823+00:00

Hi teams,

When I try to close a Task, all the methods I look up point to using CancellationTokenSourcem, but when I use it, it doesn't seem to close the task right away, it has to wait until the method finishes executing.

 Task Task;  
        CancellationTokenSource tokenSource;  
        private  async void button1_Click(object sender, EventArgs e)  
        {  
            tokenSource = new CancellationTokenSource();  
            CancellationToken ct = tokenSource.Token;  
            Task = Task.Run(() =>  
            {  
                ct.ThrowIfCancellationRequested();  
  
                while (true)  
                {  
                    if (ct.IsCancellationRequested)  
                    {  
                        ct.ThrowIfCancellationRequested();  
                    }  
                   M1();  
                }  
            }, tokenSource.Token);  
            try  
            {  
                await Task;  
            }  
            catch (OperationCanceledException ex)  
            {  
                Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {ex.Message}");  
            }  
            finally  
            {  
                tokenSource.Dispose();  
            }  
        }  
  
        private void button2_Click(object sender, EventArgs e)  
        {  
            tokenSource.Cancel();  
        }  
        public void M1()   
        {  
            Console.WriteLine("1");  
            Thread.Sl eep(3000);  
           
            Console.WriteLine("2");  
            Thread.Sl eep(3000);  
  
            Console.WriteLine("3");  
            Thread.Sl eep(3000);  
  
            Console.WriteLine("4");  
            Thread.Sl eep(3000);  
  
            Console.WriteLine("5");  
            Thread.Sl eep(3000);  
  
            Console.WriteLine("6");  
        }  

Am I using it the wrong way?

One more question, if method M1() is async Task, I thought I should be able to use awiat M1() when calling it, but I can't actually use it like this inside Task.Run, I don't quite understand why.

Thanks in advance.

Developer technologies C#
0 comments No comments
{count} votes

Accepted answer
  1. Karen Payne MVP 35,586 Reputation points Volunteer Moderator
    2022-07-21T09:30:53.767+00:00

    Here is a working example which shows progress, keeps the app responsive and provides cancellation. Full source

    using System;  
    using System.Threading;  
    using System.Threading.Tasks;  
    using System.Windows.Forms;  
      
    namespace AsyncTaskProgress2  
    {  
        public partial class Form1 : Form  
        {  
            private CancellationTokenSource _cts = new CancellationTokenSource();  
      
            public Form1()  
            {  
                InitializeComponent();  
            }  
      
            private async void StartButton_Click(object sender, EventArgs e)  
            {  
                var cancelled = false;  
                if (_cts.IsCancellationRequested == true)  
                {  
                    _cts.Dispose();  
                    _cts = new CancellationTokenSource();  
                }  
      
      
                var progressIndicator = new Progress<int>(ReportProgress);  
                  
                try  
                {  
                    await AsyncMethod(progressIndicator, _cts.Token);  
                }  
                catch (OperationCanceledException)  
                {  
                    StatusLabel.Text = "Cancelled";  
                    cancelled = true;  
                }  
      
                if (!cancelled) return;  
                  
                await Task.Delay(1000);  
                StatusLabel.Text = "Go again!";  
            }  
      
            private void CancelButton_Click(object sender, EventArgs e)  
            {  
                _cts.Cancel();  
            }  
            private static async Task AsyncMethod(IProgress<int> progress, CancellationToken ct)  
            {  
      
                for (int index = 100; index <= 120; index++)  
                {  
                    //Simulate an async call that takes some time to complete  
                    await Task.Delay(500, ct);  
      
                    if (ct.IsCancellationRequested)  
                    {  
                        ct.ThrowIfCancellationRequested();  
                    }  
      
                    progress?.Report(index);  
      
                }  
      
            }  
            private void ReportProgress(int value)  
            {  
                StatusLabel.Text = value.ToString();  
                TextBox1.Text = value.ToString();  
            }  
      
        }  
    }  
      
    
     
    
    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.