How do I cancel a Blocked Task in C# using a Cancellation Token?

柔情痞子 提交于 2019-12-22 09:58:01

问题


I have a Task which is always blocked and I have a CancellationToken passed into it which is used to cancel the task. However the Continuation task is never executed which is set to execute on Task's cancellation. The code is:

    _tokenSrc = new CancellationTokenSource();
    var cnlToken = _tokenSrc.Token;

    Task.Run(() => 
          // _stream.StartStream() blocks forever  
          _stream.StartStream(), cnlToken)
        .ContinueWith(ant =>
        {
            _logger.Warn("Stream task cancellation requested, stopping the stream");
            _stream.StopStream();
            _stream = null;
            _logger.Warn("Stream stopped and task cancelled");
        }, TaskContinuationOptions.OnlyOnCanceled);

Later somewhere else in the code ...

_tokenSrc.Cancel();

The reason I had to use a Task for _stream.StartStream() is that this call blocks forever (an api on which I have no control, note that _stream refers to a thirdparty Api which streams data from a webservice) so I had to invoke it on another thread.

What is the best way to cancel the task?


回答1:


[UPDATE]

I changed the code to below which fixed the problem:

Task.Run(() =>
{
    var innerTask = Task.Run(() => _stream.StartStream(), cToken);
    innerTask.Wait(cToken);
}, cToken)
.ContinueWith(ant =>
{
    _logger.Warn("Stream task cancellation requested, stopping the stream");
    _stream.StopStream();
    _stream = null;
    _logger.Warn("Stream stopped and task cancelled");
}, TaskContinuationOptions.OnlyOnCanceled);



回答2:


You can use the Register method on CancellationToken to register a delegate that will be invoked when cancellation is requested. In the delegate you call the method that unblocks your blocked operation.

Something like:

_tokenSrc = new CancellationTokenSource();
var cnlToken = _tokenSrc.Token;

var task = Task.Factory.StartNew(() =>
{
    using(var tokenReg = cnlToken.Register(() => 
        {
            _logger.Warn("Stream task cancellation requested, stopping the stream");
            _stream.StopStream();
            _stream = null;
            _logger.Warn("Stream stopped and task cancelled");
        }))
    {
        _stream.StartStream(), cnlToken)
    }
}, cnlToken);

MSDN "How to: Register Callbacks for Cancellation Requests"




回答3:


How to use a cancellation token is clearly described here: http://msdn.microsoft.com/en-us/library/dd997396(v=vs.110).aspx with a suggested pattern to follow.

I'll report the example in case the page goes down:

using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
    static void Main()
    {

        var tokenSource2 = new CancellationTokenSource();
        CancellationToken ct = tokenSource2.Token;

        var task = Task.Factory.StartNew(() =>
        {

            // Were we already canceled?
            ct.ThrowIfCancellationRequested();

            bool moreToDo = true;
            while (moreToDo)
            {
                // Poll on this property if you have to do 
                // other cleanup before throwing. 
                if (ct.IsCancellationRequested)
                {
                    // Clean up here, then...
                    ct.ThrowIfCancellationRequested();
                }

            }
        }, tokenSource2.Token); // Pass same token to StartNew.

        tokenSource2.Cancel();

        // Just continue on this thread, or Wait/WaitAll with try-catch: 
        try
        {
            task.Wait();
        }
        catch (AggregateException e)
        {
            foreach (var v in e.InnerExceptions)
                Console.WriteLine(e.Message + " " + v.Message);
        }

        Console.ReadKey();
    }
}

There is an even more in-depth example here: http://msdn.microsoft.com/en-us/library/dd537607(v=vs.110).aspx but the first one should be enough for your scenario.



来源:https://stackoverflow.com/questions/22735533/how-do-i-cancel-a-blocked-task-in-c-sharp-using-a-cancellation-token

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!