I need to spawn some long running tasks in ASP.NET WebAPI, and I chose to do that using QueueBackgroundWorkItem.
My question is -
I need to implement a WhenAll mechanism with those tasks, meaning - I need to know when some tasks has finished, and then to perform some other task.
How can that be done using QueueBackgroundWorkItem? I couldn't find a way to do that, since it returns void, and accepts Action.
Thanks!
You can use TaskCompletionSource to create a helper method like this:
public static Task RunViaQueueBackgroundWorkItem(Action<CancellationToken> action)
{
TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
HostingEnvironment.QueueBackgroundWorkItem((ct) =>
{
try
{
action(ct);
if (ct.IsCancellationRequested)
tcs.TrySetCanceled();
else
tcs.TrySetResult(0);
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
});
return tcs.Task;
}
This method will return a task that will complete after the action completes. Note that it handles the case where an exception occurs during the invocation of the action. It also handles the case if cancellation is requested.
Here is an example of how you can use it:
public async Task<string> Get(int id)
{
var t1 = RunViaQueueBackgroundWorkItem(ct => DoSomeTask1(ct));
var t2 = RunViaQueueBackgroundWorkItem(ct => DoSomeTask2(ct));
await Task.WhenAll(t1, t2);
//...
}
For completeness, here is the helper method for the other overload of QueueBackgroundWorkItem:
public static Task RunViaQueueBackgroundWorkItem(Func<CancellationToken,Task> asyncAction)
{
TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
HostingEnvironment.QueueBackgroundWorkItem(async (ct) =>
{
try
{
await asyncAction(ct);
if (ct.IsCancellationRequested)
tcs.TrySetCanceled();
else
tcs.TrySetResult(0);
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
});
return tcs.Task;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With