如何创建已取消的任务

时间:2014-08-26 16:29:38

标签: task-parallel-library async-await c#-5.0 cancellation-token

我正在编写一个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根本没有帮助我。

2 个答案:

答案 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