简体   繁体   English

给定超时后,CancellationTokenSource不会取消任务

[英]CancellationTokenSource does not cancel task after given timeout

I am learning TAP and I like to explore TPL dataflow using unit tests. 我正在学习TAP,并且我喜欢使用单元测试来探索TPL数据流。 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 . 我期望它提高第一行中定义的超时并捕获OperationCanceledException ,但是在await tcs.Task之后,我总是以Assert.Fail await tcs.Task Could someone explain me what is not going well with my assumptions? 有人可以解释一下我的假设进行得不好吗?

TaskCompletionSource doesn't accept a CancellationToken . TaskCompletionSource不接受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 . 它确实接受Object状态,并且您可以从技术上将CancellationToken传递给它,但是它不会做任何事情,尤其是不要取消TaskCompletionSource

If you want to cancel the TaskCompletionSource you can do that with a simple timeout: 如果要取消TaskCompletionSource ,则可以通过简单的超时来完成:

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: 您还可以创建一个TaskCompletionSource ,它接受CancellationToken并在取消TaskCompletionSourceTaskCompletionSource取消:

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());
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 CancellationTokenSource 不取消任务 - CancellationTokenSource does not cancel the task CancellationTokenSource是否会突然取消? - Does a CancellationTokenSource cancel abruptly? 我是否需要创建一个新的CancellationTokenSource(); 任务取消后? - Do I need to create a new CancellationTokenSource(); after a task cancel? 无法通过CancellationTokenSource.Cancel()取消任务 - Cannot cancel a task via CancellationTokenSource.Cancel() 在任务中调用CancellationTokenSource.Cancel()不会将Task.IsCanceled设置为true - Calling CancellationTokenSource.Cancel() within a task does not set Task.IsCanceled to true 当CancellationTokenSource不可用时,如何取消任务? - how to cancel a Task when the CancellationTokenSource is not available? 为什么取消后调用CancellationTokenSource不能将任务状态更改为取消 - Why doesn't the status of a task change to canceled after cancel is called by CancellationTokenSource 如何在超时后取消任务等待 - How to cancel Task await after a timeout period 具有 CancellationTokenSource 和超时 memory 的通道在处理后泄漏 - Channels with CancellationTokenSource with timeout memory leak after dispose 我应该使用CancellationTokenSource还是CancellationToken取消.NET中的任务 - Should I use CancellationTokenSource or CancellationToken to Cancel a task in .NET
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM