简体   繁体   中英

CancellationTokenSource does not cancel task after given timeout

I am learning TAP and I like to explore TPL dataflow using unit tests. I have the following one that I am unable to understand:

var cts = new CancellationTokenSource(500);
var tcs = new TaskCompletionSource<bool>(cts.Token);
var agent = new ActionBlock<FakeMessage>( async evt =>
{
    await Task.Delay(5000);
    tcs.SetResult(true);
});

agent.Post(new FakeMessage());
try
{
    var result = await tcs.Task;
    Assert.Fail();
}
catch (OperationCanceledException ex)
{
    Assert.IsTrue(true);
}
catch (Exception e)
{
    Assert.Fail();
}

I was expecting it to raise the timeout defined on the first line and to catch the OperationCanceledException , but I always end up with the Assert.Fail following await tcs.Task . Could someone explain me what is not going well with my assumptions?

TaskCompletionSource doesn't accept a CancellationToken .

It does accept an Object state and you can technically pass a CancellationToken into it, but it wouldn't do anything, especially not cancel the TaskCompletionSource .

If you want to cancel the TaskCompletionSource you can do that with a simple timeout:

Task.Delay(500).ContinueWith(t => tcs.SetCancelled());

You can also create a TaskCompletionSource that does accept a CancellationToken and cancels itself when the TaskCompletionSource is cancelled:

class TaskCompletionSourceWithCancellation<T> : TaskCompletionSource<T>
{
    public CancellationToken CancellationToken { get; }

    public TaskCompletionSourceWithCancellation(CancellationToken cancellationToken)
    {
        CancellationToken = cancellationToken;
        var cancellationTokenRegistration =
            cancellationToken.Register(
                _ => ((TaskCompletionSourceWithCancellation<TResult>)_).TrySetCanceled(),
                this);
        Task.ContinueWith(_ => cancellationTokenRegistration.Dispose());
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM