Suppose I want to ensure that a task object which is returned from an asynchronous method will transition into the canceled state, due to a cancellation request by the caller.
Catch is: this should occur regardless of how the asynchronous methods consumed by the aforementioned method are implemented and whether or not they ever complete.
Consider the following extension method:
public static Task<T> ToTask<T>(this CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<T>();
cancellationToken.Register(() => { tcs.SetCanceled(); });
return tcs.Task;
}
I can now consume such a task to ensure said scenario:
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;
}
My questions are:
1) Are there any issues with this approach?
2) Is there a built in API to facilitate such a use case
Thanks!
Suppose I want to ensure the cancellation of an asynchronous operation, Regardless of how the actual operation is implemented and whether or not it completes.
That is not possible unless you wrap the code into a separate process.
When I say "ensure", I mean to say that the task denoting said operation transitions into the canceled state.
If you just want to cancel the task (and not the operation itself), then sure, you can do that.
Are there any issues with this approach?
There's some tricky edge cases here. In particular, you need to dispose the result of Register
if the task completes successfully.
I recommend using the WaitAsync
extension method in my AsyncEx.Tasks
library:
public Task<Item> ProvideItemAsync(CancellationToken cancellationToken)
{
return _itemProvider.ProvideItemAsync(cancellationToken).WaitAsync(cancellationToken);
}