I am working on a windows service and I have two related calls that depend on each other, that I want to run asynchronously for each "pair" or "set" of calls. There are several ways to do this and I have tried a few different was and settles on this because it is convenient to have one block of code to deal with as opposed to two separate blocks with their own await Task.WhenAll()
calls. In my testing this seems to work as expected but I have never chained two tasks together like this before and I am wondering if this is a good way to do it and if there might be a more appropriate way to get the same result (a single block of code).
Here's what I have. Does this look like a reasonable way to chain tasks and if not, please tell me why.
Thanks in advance. -Frank
//get all pending batches
foreach (string batchId in workload)
{
try
{
// I am using this ContinueWith pattern here to aggregate the Tasks
// which makes it more convenient to handle exceptions in one place
Task t = bll.GetIncomingBatchAsync(batchId).ContinueWith(
task => bll.SaveIncomingBatchAsync(task.Result),
TaskContinuationOptions.OnlyOnRanToCompletion);
saveBatchTasks.Add(t);
}
catch (Exception ex)
{
_logger.WriteError(ex, "ProcessWorkloadAsync error building saveBatchTasks!");
throw ex;
}
}
try
{
await Task.WhenAll(saveBatchTasks);
}
catch (Exception ex)
{
_logger.WriteError(ex, "ProcessWorkloadAsync error executing saveBatchTasks!");
throw ex;
}
No, you should not use ContinueWith
. Use await
instead.
If you're worried about separating the logic across two functions, just use a local function:
//get all pending batches
foreach (string batchId in workload)
{
try
{
async Task GetAndSave()
{
var result = await bll.GetIncomingBatchAsync(batchId);
await bll.SaveIncomingBatchAsync(result);
}
saveBatchTasks.Add(GetAndSave());
}
catch (Exception ex)
{
_logger.WriteError(ex, "ProcessWorkloadAsync error building saveBatchTasks!");
throw ex;
}
}