确保取消某些任务

时间:2016-10-26 12:59:34

标签: c# asynchronous task-parallel-library cancellation

假设我想确保由于调用者的取消请求,从异步方法返回的任务对象将转换为已取消状态。

Catch is:无论上述方法消耗的异步方法是如何实现的,以及它们是否完成,都应该发生这种情况。

考虑以下扩展方法:

    public static Task<T> ToTask<T>(this CancellationToken cancellationToken)
    {
        var tcs = new TaskCompletionSource<T>();
        cancellationToken.Register(() => { tcs.SetCanceled(); });
        return tcs.Task;
    }

我现在可以使用这样的任务来确保上述情况:

 public async Task<Item> ProvideItemAsync(CancellationToken cancellationToken)
    {
        Task<Item> cancellationTask = cancellationToken.ToTask<Item>();

        Task<Item> itemTask = _itemProvider.ProvideItemAsync(cancellationToken);

        Task<Task<Item>> compoundTask = Task.WhenAny(cancellationTask, itemTask);

        Task<Item> finishedTask = await compoundTask;

        return await finishedTask;
    }

我的问题是:

1)这种方法有什么问题吗?
2)是否有内置的API来促进这种用例

谢谢!

1 个答案:

答案 0 :(得分:4)

  

假设我想确保取消异步操作,   无论实际操作如何实施以及是否完成。

除非将代码封装到单独的进程中,否则这是不可能的。

  

当我说&#34;确保&#34;时,我的意思是说表示所述操作的任务转换为已取消状态。

如果你只想取消任务(而不是操作本身),那么你可以这样做。

  

这种方法有什么问题吗?

这里有一些棘手的边缘案例。特别是,如果任务成功完成,则需要处理Register的结果。

我建议使用WaitAsync extension method中的AsyncEx.Tasks library

public Task<Item> ProvideItemAsync(CancellationToken cancellationToken)
{
  return _itemProvider.ProvideItemAsync(cancellationToken).WaitAsync(cancellationToken);
}