我们要并行执行调用10个任务,并并行处理10个结果中的每一个。
要实现,创建了一个任务列表,并使用continuewith每个任务都与异步方法相关联,
摘要
private async Task<List<bool>> TransformJobsAsync(
List<T> jobs)
{
var result = new List<bool>() { true };
var tasks = new List<Task<bool>>(jobs.Count);
try
{
foreach (var j in jobs)
{
tasks .Add(InvokeSomeAsync(j).ContinueWith(x => HandleResultAsync(x, j)).Unwrap());
}
await Task.WhenAll(tasks);
return tasks.Select(x => x.Result).ToList();
}
catch (Exception ex)
{
result = new List<bool>() { false };
}
return result;
}
Task<(T response, T job)> InvokeSomeAsync (T job)
{
var cts = new CancellationTokenSource();
try
{
cts.CancelAfter(30000);
var response = await SomeThirdPartyApi(request, cts.Token);
if (response.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
}
return (response, job);
}
catch (OperationCanceledException opexException)
{
contextMessage = Messages.TranformationExecutionTimedOut;
}
catch (Exception ex)
{
contextMessage = Messages.UnHandledException;
}
finally
{
cts = null; //why? suggested pattern? review.
}
return await Task.FromException<(response, T Job)>(
throw new Exception());
}
async Task<bool> HandleResultAsync(Task<(T response, T job)> task, T job)
{
try
{
if (task.Status == TaskStatus.RanToCompletion)
{
if (task.Result.Status)
{
response = await CallMoreAsync(task.Result.reponse,
job, currentServiceState);
}
else
{
//log returned response = false
}
}
else
{
//log task failed
}
}
catch (Exception ex)
{
response = false;
}
finally
{
await DoCleanUpAsync();
}
return response;
}
我想知道是否有更好的模式,continuewith不适合使用!
有时我们会收到此错误,System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError错误)
答案 0 :(得分:0)
您不应使用ContinueWith
。 ContinueWith
是一种与await
相同的低级危险方法。现代代码应改用await
。
要结合两个异步操作(例如InvokeSomeAsync
和HandleResultAsync
),请引入async
方法:
async Task<bool> InvokeAndHandleResultAsync<T>(T job)
{
var task = InvokeSomeAsync(job);
return await HandleResultAsync(task, job);
}
然后可以在您的foreach
中使用它:
foreach (var j in jobs)
{
tasks.Add(InvokeAndHandleResultAsync(j));
}
其他说明:
CancellationTokenSource
应该被处置。await Task.From*
通常是一个黄色标志。Task.Status
是一个危险信号。bool
状态为contextMessage
的结果。我会这样写:
async Task InvokeAndHandleResultAsync<T>(T job)
{
using (var cts = new CancellationTokenSource(30000))
{
try
{
var response = await SomeThirdPartyApi(request, cts.Token);
if (!response.Status)
{
//log returned response = false
return;
}
await CallMoreAsync(response, job, currentServiceState);
}
catch (Exception ex)
{
//log task failed
}
finally
{
await DoCleanUpAsync();
}
}
}
此外,您可以简化该代码,而不是构建任务列表:
private async Task TransformJobsAsync(List<T> jobs)
{
return Task.WhenAll(jobs.Select(j => InvokeAndHandleResult(j)));
}