[英]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
并在取消TaskCompletionSource
时TaskCompletionSource
取消:
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.