How do I abort/cancel TPL Tasks?

前端 未结 12 2081
佛祖请我去吃肉
佛祖请我去吃肉 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条回答
  • 2020-11-22 11:46

    You should not try to do this directly. Design your tasks to work with a CancellationToken, and cancel them this way.

    In addition, I would recommend changing your main thread to function via a CancellationToken as well. Calling Thread.Abort() is a bad idea - it can lead to various problems that are very difficult to diagnose. Instead, that thread can use the same Cancellation that your tasks use - and the same CancellationTokenSource can be used to trigger the cancellation of all of your tasks and your main thread.

    This will lead to a far simpler, and safer, design.

    0 讨论(0)
  • 2020-11-22 11:47

    Like this post suggests, this can be done in the following way:

    int Foo(CancellationToken token)
    {
        Thread t = Thread.CurrentThread;
        using (token.Register(t.Abort))
        {
            // compute-bound work here
        }
    }
    

    Although it works, it's not recommended to use such approach. If you can control the code that executes in task, you'd better go with proper handling of cancellation.

    0 讨论(0)
  • 2020-11-22 11:47

    Task are being executed on the ThreadPool (at least, if you are using the default factory), so aborting the thread cannot affect the tasks. For aborting tasks, see Task Cancellation on msdn.

    0 讨论(0)
  • 2020-11-22 11:51

    You can't. Tasks use background threads from the thread pool. Also canceling threads using the Abort method is not recommended. You may take a look at the following blog post which explains a proper way of canceling tasks using cancellation tokens. Here's an example:

    class Program
    {
        static void Main()
        {
            var ts = new CancellationTokenSource();
            CancellationToken ct = ts.Token;
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    // do some heavy work here
                    Thread.Sleep(100);
                    if (ct.IsCancellationRequested)
                    {
                        // another thread decided to cancel
                        Console.WriteLine("task canceled");
                        break;
                    }
                }
            }, ct);
    
            // Simulate waiting 3s for the task to complete
            Thread.Sleep(3000);
    
            // Can't wait anymore => cancel this task 
            ts.Cancel();
            Console.ReadLine();
        }
    }
    
    0 讨论(0)
  • 2020-11-22 11:52

    You can use a CancellationToken to control whether the task gets cancelled. Are you talking about aborting it before it's started ("nevermind, I already did this"), or actually interrupting it in middle? If the former, the CancellationToken can be helpful; if the latter, you will probably need to implement your own "bail out" mechanism and check at appropriate points in the task execution whether you should fail fast (you can still use the CancellationToken to help you, but it's a little more manual).

    MSDN has an article about cancelling Tasks: http://msdn.microsoft.com/en-us/library/dd997396.aspx

    0 讨论(0)
  • 2020-11-22 11:53

    Tasks have first class support for cancellation via cancellation tokens. Create your tasks with cancellation tokens, and cancel the tasks via these explicitly.

    0 讨论(0)
提交回复
热议问题