我正在编写一个Stream类,并在ReadAsync方法中被阻止。请看一下代码,我认为它可以更好地解释我用英语做的情况。
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken)
{
if (!cancellationToken.IsCancellationRequested)
{
return _connection.ReceiveAsync(new ArraySegment<byte>(buffer, offset, count));
}
return // <--------------- what here?
}
使用ILSpy我可以看到其他Stream类返回已取消的任务,如下所示:
return new Task<TResult>(true, default(TResult), TaskCreationOptions.None, cancellationToken);
但是,Task的构造函数是内部的,我无法调用它。
Google根本没有帮助我。
答案 0 :(得分:12)
我知道创建已取消任务的最直接方法是使用TaskCompletionSource
:
var tcs = new TaskCompletionSource<int>();
tcs.TrySetCanceled();
return tcs.Task;
如果您之前没有使用过,TaskCompletionSource
提供了“承诺风格”的任务,基本上可以让您说“在这里,现在就拿这个Task
,我会提供每当我准备好时,结果(或报告错误/取消)。“当您想要自己安排/协调工作时,它非常有用,而不是仅仅依靠TaskScheduler
。
或者,如果您使用async/await
重写方法,则可以强制取消例外自动传播到结果Task
:
public async override Task<int> ReadAsync(
byte[] buffer,
int offset,
int count,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
return await _connection.ReceiveAsync(
new ArraySegment<byte>(
buffer,
offset,
count));
}
答案 1 :(得分:9)
next version of .Net (v4.5.3)正在添加一种利用该内部构造函数创建已取消任务的方法。有通用和非通用版本:
var token = new CancellationToken(true);
Task task = Task.FromCanceled(token);
Task<int> genericTask = Task.FromCanceled<int>(token);
请注意,在调用CancellationToken
FromCanceled