9

我正在编写一个 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 的构造函数是内部的,我无法调用它。

谷歌根本没有帮助我。

4

2 回答 2

15

.Net (v4.5.3)的下一个版本添加了一种利用该内部构造函数创建取消任务的方法。有通用和非通用版本:

var token = new CancellationToken(true);
Task task = Task.FromCanceled(token);
Task<int> genericTask = Task.FromCanceled<int>(token);

请记住,CancellationToken在调用之前必须取消正在使用的FromCanceled

于 2014-10-06T23:26:54.790 回答
15

我知道创建取消任务的最直接方法是使用TaskCompletionSource

var tcs = new TaskCompletionSource<int>();
tcs.TrySetCanceled();
return tcs.Task;

如果你之前没用过,TaskCompletionSource提供一个“promise-style”任务,基本上可以让你说,“这里,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));
}
于 2014-08-26T16:32:23.217 回答