我正在为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)});
我是否过度考虑优化?是否有更好的方法还可以并行执行单个功能?
//应该并行执行,而不仅仅是在单独的线程上执行
您几乎从不希望并行代码在ASP.NET服务器上运行。您可能很快就会饿死线程,从而破坏了服务器响应其他请求的能力。
但是如果您绝对确定这是您要执行的操作,则需要使BuildDomTree
本身平行,最好使用Parallel
或Parallel LINQ。 Parallel.For(0, 1, ...)
毫无意义-因为Parallel.For
中只有一个索引值,因此不会增加任何并行度。
然后在ASP.NET上存在“即兴即忘”的问题,这很危险。真正的“失火忘却”是指“我不在乎when完成,if完成或wh是否失败”,这种情况极为罕见。除非您采取措施将您的后台工作通知给ASP.NET,否则可以在没有警告,没有异常且没有日志的情况下终止它。