-3

使用一些异步方法在 c# 中进行并行处理的最佳方法是什么。让我用一些简单的代码来解释

示例场景:我们有一个人和 1000 个来自他们的文本文件。我们要检查他的文本文件不包含敏感关键字,如果他的文本文件之一包含敏感关键字,我们将他标记为不可信。检查这一点的方法是异步方法,只要我们发现其中一个敏感关键字不需要进一步处理,就必须为那个人打破检查循环。

为了获得最佳性能并使其如此快速,我们必须使用并行处理简单的伪代码:

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 asyncasync/await 和 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");
4

1 回答 1

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");
于 2017-05-09T07:13:14.873 回答