使用某些异步方法在c#中进行并行处理的最佳方法是什么。 让我用一些简单的代码解释
示例场景:我们有一个人和1000个文本文件。我们想检查他的文本文件是否包含敏感关键字,如果他的某个文本文件包含敏感关键字,我们会将其标记为不受信任。检查这个的方法是异步方法,并且我们发现其中一个敏感关键字不需要进一步处理,并且必须为该人打破检查循环。
为了获得最佳性能并使其如此之快,我们必须使用并行处理 简单的psudocode:
boolean sesitivedetected=false;
Parallel.ForEach(textfilecollection,async (textfile,parallelloopstate)=>
{
if (await hassensitiveasync(textfile))
{
sensitivedetected=true;
parallelloopstate.break()
}
}
if (sensitivedetected)
markuntrusted(person)
问题是Parallel.ForEach
不等到异步任务完成,因此一旦创建任务完成,就会运行语句if (sensitivedetected)
。
我阅读了其他问题,例如write parallel.for with async和async/await and Parallel.For以及许多其他页面。
当您需要在以后收集和使用异步方法的结果时,此主题非常有用,但在我的方案中,应尽快结束循环执行。
更新:示例代码:
Boolean detected=false;
Parallel.ForEach(UrlList, async (url, pls) =>
{
using (HttpClient hc = new HttpClient())
{
var result = await hc.GetAsync(url);
if ((await result.Content.ReadAsStringAsync()).Contains("sensitive"))
{
detected = true;
pls.Break();
}
}
});
if (detected)
Console.WriteLine("WARNING");
答案 0 :(得分:0)
实现你需要的最简单的方法(而不是你想要的,因为线程是邪恶的)。是使用ReactiveExtensions。
var firstSensitive = await UrlList
.Select(async url => {
using(var http = new HttpClient()
{
var result = await hc.GetAsync(url);
return await result.Content.ReadAsStringAsync();
}
})
.SelectMany(downloadTask => downloadTask.ToObservable())
.Where(result => result.Contains("sensitive"))
.FirstOrDefaultAsync();
if(firstSensitive != null)
Console.WriteLine("WARNING");
限制并发HTTP查询的数量:
int const concurrentRequestLimit = 4;
var semaphore = new SemaphoreSlim(concurrentRequestLimit);
var firstSensitive = await UrlList
.Select(async url => {
await semaphore.WaitAsync()
try
using(var http = new HttpClient()
{
var result = await hc.GetAsync(url);
return await result.Content.ReadAsStringAsync();
}
finally
semaphore.Release();
})
.SelectMany(downloadTask => downloadTask.ToObservable())
.Where(result => result.Contains("sensitive"))
.FirstOrDefaultAsync();
if(firstSensitive != null)
Console.WriteLine("WARNING");