How do I abort/cancel TPL Tasks?

前端 未结 12 2290
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-22 11:42

In a thread, I create some System.Threading.Task and start each task.

When I do a .Abort() to kill the thread, the tasks are not aborted.

12条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-11-22 11:59

    I use a mixed approach to cancel a task.

    • Firstly, I'm trying to Cancel it politely with using the Cancellation.
    • If it's still running (e.g. due to a developer's mistake), then misbehave and kill it using an old-school Abort method.

    Checkout an example below:

    private CancellationTokenSource taskToken;
    private AutoResetEvent awaitReplyOnRequestEvent = new AutoResetEvent(false);
    
    void Main()
    {
        // Start a task which is doing nothing but sleeps 1s
        LaunchTaskAsync();
        Thread.Sleep(100);
        // Stop the task
        StopTask();
    }
    
    /// 
    ///     Launch task in a new thread
    /// 
    void LaunchTaskAsync()
    {
        taskToken = new CancellationTokenSource();
        Task.Factory.StartNew(() =>
            {
                try
                {   //Capture the thread
                    runningTaskThread = Thread.CurrentThread;
                    // Run the task
                    if (taskToken.IsCancellationRequested || !awaitReplyOnRequestEvent.WaitOne(10000))
                        return;
                    Console.WriteLine("Task finished!");
                }
                catch (Exception exc)
                {
                    // Handle exception
                }
            }, taskToken.Token);
    }
    
    /// 
    ///     Stop running task
    /// 
    void StopTask()
    {
        // Attempt to cancel the task politely
        if (taskToken != null)
        {
            if (taskToken.IsCancellationRequested)
                return;
            else
                taskToken.Cancel();
        }
    
        // Notify a waiting thread that an event has occurred
        if (awaitReplyOnRequestEvent != null)
            awaitReplyOnRequestEvent.Set();
    
        // If 1 sec later the task is still running, kill it cruelly
        if (runningTaskThread != null)
        {
            try
            {
                runningTaskThread.Join(TimeSpan.FromSeconds(1));
            }
            catch (Exception ex)
            {
                runningTaskThread.Abort();
            }
        }
    }
    

提交回复
热议问题