簡體   English   中英

有什么方法可以在並行任務完成后立即訪問結果?

[英]Any way of accessing results from Parallel tasks as soon as they are done?

目前,我並行運行多個任務並將結果放在一個列表中,我從中使用數據。 我想並行運行我的所有任務,但是一旦完成一項任務以直接訪問數據,它就是數據

這是我當前的代碼:

await Task.Run(async () =>
            {
                Parallel.For(0, k, i =>
                {
                    var tt = Sites.oneNews(cat, sites[i]);
                    results.Add(tt.Result);
                });
            });

我等不及他們都完成了,因為其中一些需要太長時間。 我需要在結果單獨返回后立即訪問它

我建議您閱讀那篇文章- 它幫助我在我的一個項目中實現了一個通用邏輯,並且也被 dotnet 文檔推薦(我還將鏈接幫助我找到該資源的 C# 文檔)。

只需將results設置為像BlockingCollection這樣的線程安全的生產者-消費者集合。 它具有GetConsumingEnumerable方法,該方法返回一個 IEnumerable,一旦另一個代碼部分將其添加到集合中,它將產生一個項目。

var results = new BlockingCollection<Result>();

async Task ProducerAsync()
{
  await Task.Run(() => // I removed the async here as it was not needed
  {
    Parallel.For(0, k, i =>
    {
      var tt = Sites.oneNews(cat, sites[i]);
      results.Add(tt.Result);
    });
  });

  results.CompleteAdding(); // notify any enumerable that no more items will arrive
}

void Consumer()
{
  foreach (var result in results.GetConsumingEnumerable())
  {
    // each result will arrive here as soon as it becomes available
  }
}

或者,如果您想以生成結果的相同方法使用結果(請注意,我將調用移至Task.Run內的CompleteAdding ):

var results = new BlockingCollection<Result>();

var producerTask = Task.Run(() => // I removed the async here as it was not needed
{
  Parallel.For(0, k, i =>
  {
    var tt = Sites.oneNews(cat, sites[i]);
    results.Add(tt.Result);
  });

  results.CompleteAdding(); // notify any enumerable that no more items will arrive
});

foreach (var result in results.GetConsumingEnumerable())
{
  // each result will arrive here as soon as it becomes available
}

await producerTask;

在不確切知道您在什么上下文中使用此代碼的情況下,我可以說您不需要使用 async 關鍵字,因為您正在運行的操作不是異步的。 在任何情況下,如果您需要處理任何集合更改事件,那么您可以使用ObservableCollection並監聽任何CollectionChanged事件並處理添加的tt.Result 但是請記住,由於您使用的是並行性,這意味着由於您的代碼不是異步的,因此每個循環都應該在同一時間完成(取決於操作的強度)。 同樣,我不知道確切的上下文,所以我不能說更多。

也許我誤解了,但是有什么能阻止你從並行中調用一個方法來處理結果呢? 代碼如下。 我們已經在不同的線程上,因此處理一組結果不會阻塞處理下一組結果,這就是 @ckuri 的 Consumer for 循環中發生的事情,它處理同一線程上的所有結果。 當然,這僅在處理它們很慢時才重要。

這似乎微不足道,我想知道我是否沒有誤解實際問題。

await Task.Run(() =>
{
    Parallel.For(0, k, i =>
    {
        var tt = Sites.oneNews(cat, sites[i]);
        var result = tt.Result;
        results.Add(result);
        // Call a method to handle the results as they arise
        HandleResult(result);
    });
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM