首页 > 解决方案 > 使用 Parallel ForEach 在 API 中发布并单个处理每个响应

问题描述

我想知道我生成的代码是否是好的实践并且不会产生泄漏,我有超过 7000 个对象 Participant 我将单独推送并处理响应以将“外部”ID 保存在我们的数据库中。首先,我使用列表 pPartcipant 上的 Parallel ForEach:

Parallel.ForEach(pParticipant, participant =>
{
try
{
    //Create
    if (participant.id == null)
    {
        ExecuteRequestCreate(res, participant);
    }
    else
    {//Update
        ExecuteRequestUpdate(res, participant);
    }
}
catch (Exception ex)
{
    LogHelper.Log("Fail Parallel ", ex);
}
});

然后我做了一个经典的(不是异步请求),但是在我需要“处理”响应之后(在控制台中打印,以异步模式保存在文本文件中,并在我的数据库中更新)

    private async void ExecuteRequestCreate(Uri pRes, ParticipantDo pParticipant)
    {
        try
        {
            var request = SetRequest(pParticipant);

            //lTaskAll.Add(Task.Run(() => { ExecuteAll(request, pRes, pParticipant); }));
            //Task.Run(() => ExecuteAll(request, pRes, pParticipant));
            var result = RestExecute(request, pRes);
            await HandleResult(result, pParticipant);
            //lTaskHandle.Add(Task.Run(() => { HandleResult(result, pParticipant); }));
        }
        catch (Exception e)
        {
            lTaskLog.Add(LogHelper.Log(e.Message + " " + e.InnerException));
        }
    } 

我应该运行一个新任务来处理结果(如评论)?它会提高性能吗?在评论中,您可以看到我创建了一个任务列表,因此我可以在最后等待(任务日志是我在文本文件中写入的所有任务):

       int nbtask = lTaskHandle.Count;
        try
        {
            Task.WhenAll(lTaskHandle).Wait();
            Task.WhenAll(lTaskLog).Wait();
        }

        catch (Exception ex)
        {
            LogHelper.Log("Fail on API calls tasks", ex);
        }

我没有任何界面它是一个控制台程序。

标签: c#apiforeachparallel-processing

解决方案


我想知道我生成的代码是否是好的做法

不; 你应该避免async void,也应该避免Parallel工作async

这是一个类似的顶级方法,它使用异步并发而不是Parallel

var tasks = pParticipant
    .Select(participant =>
    {
      try
      {
        //Create
        if (participant.id == null)
        {
          await ExecuteRequestCreateAsync(res, participant);
        }
        else
        {//Update
          await ExecuteRequestUpdateAsync(res, participant);
        }
      }
      catch (Exception ex)
      {
        LogHelper.Log("Fail Parallel ", ex);
      }
    })
    .ToList();
await Task.WhenAll(tasks);

你的工作方法应该async Taskasync void

private async Task ExecuteRequestCreateAsync(Uri pRes, ParticipantDo pParticipant)
{
  try
  {
    var request = SetRequest(pParticipant);
    var result = await RestExecuteAsync(request, pRes);
    await HandleResult(result, pParticipant);
  }
  catch (Exception e)
  {
    LogHelper.Log(e.Message + " " + e.InnerException);
  }
} 

推荐阅读