以并行方式运行计算繁重的任务,而无需等待C#中的结果

问题描述 投票:0回答:1

我正在为HTTP请求创建自定义的实现处理程序,该请求应并行执行耗时的代码(每个请求50ms)。我不需要将任何东西退还给用户,因此我唯一关心的是在单独的CPU内核上的快速执行。这是配置实现:

public void Configure(IApplicationBuilder app){
  app.Run(context => {
    return Task.Run(async () => {
      await executeHandle(context);
    });
  });
}

在每个请求上,都会调用executeHandle。

private static readonly Object obj = new Object();
public HashSet<string> arrayOfStrings = new HashSet();

public async Task executeHandle(HttpContext context){
  if (context.Request.Body != null){
    using (var ms = new MemoryStream()){
      await Microsoft.AspNetCore.Http.Extensions.StreamCopyOperation.CopyToAsync(
          context.Request.Body, ms, s_maxInMemoryData, context.RequestAborted);
      var requestBody = ms.ToArray();
      string html = Encoding.UTF8.GetString(responseBody);
      // inspect arrayOfStrings HashSet on each request and execude logic based on
      // items found
      // build DOM tree using HTMLAgilePack or some other library, takes 50ms
      // should execute in parallel, not just on a separate thread
      // call BuildDomTree();
    }
  }
}

public static void BuildDomTree(){
  // build DOM and update HashSet
  lock(obj){
   arrayOfStrings.add("somestring")
  }
}

由于性能至关重要,因此我想听听一些专家对如何调用BuildDomTree的意见。请注意,我不会向用户返回任何内容,但仍需要尽快获得结果。一种选择是使用

Task.Run(() => {BuildDomTree()});

问题是它仅在不同的线程上执行,而不一定并行执行。另一种选择是使用Parallel.For并将其包装在Task.Run中,以避免阻塞:

Task.Run(() => {Parallel.For(0, 1, BuildDomTree)});

我是否过度考虑优化?是否有更好的方法还可以并行执行单个功能?

c# parallel-processing async-await task
1个回答
1
投票

//应该并行执行,而不仅仅是在单独的线程上执行

您几乎从不希望并行代码在ASP.NET服务器上运行。您可能很快就会饿死线程,从而破坏了服务器响应其他请求的能力。

但是如果您绝对确定这是您要执行的操作,则需要使BuildDomTree本身平行,最好使用Parallel或Parallel LINQ。 Parallel.For(0, 1, ...)毫无意义-因为Parallel.For中只有一个索引值,因此不会增加任何并行度。

然后在ASP.NET上存在“即兴即忘”的问题,这很危险。真正的“失火忘却”是指“我不在乎when完成,if完成或wh是否失败”,这种情况极为罕见。除非您采取措施将您的后台工作通知给ASP.NET,否则可以在没有警告,没有异常且没有日志的情况下终止它。

© www.soinside.com 2019 - 2024. All rights reserved.