簡體   English   中英

等待來自多個對象的任務

[英]Awaiting tasks from multiple objects

我有一個使用MEF加載插件的應用程序。 所有這些插件均符合以下接口:

public interface IPlugin {
    Task Start();
}

所有方法都實現為asyncpublic async Task Start()

當應用程序運行時,我有一個IEnumerable<IPlugin>屬性可用於所有插件。 問題基本上是我如何可以並行運行所有Start()方法並等待所有方法完成?

我知道Parallel.ForEach(plugins, plugin => plugin.Start()) ,但這不是等待的,執行將在所有插件啟動之前繼續進行。

最有前途的解決方案似乎是Task.WhenAll() ,但是我不知道如何在不添加一些腳手架的情況下向其中發送方法的未知列表(這似乎有些開銷)。

我該怎么做?

這是一個單線:

await Task.WhenAll(plugins.Select(p => p.Start()));

插件將異步運行,但不能並行運行。 如果出於某種原因想要將插件顯式分派到線程池,則可以將帶有async lambda的Task.Run添加到Select

你可以做:

var tasks = new List<Task>();
foreach(var plugin in plugins) 
{
   var task = plugin.Start();
   tasks.Add(task);
}
await Task.WhenAll(tasks); 

您可以使用Microsoft的Reactive Framework來確保這是可以等待的,異步且並行發生的。

await
    plugins
        .ToObservable()
        .SelectMany(plugin => Observable.FromAsync(() => plugin.Start()))
        .ToArray();

如您所見, Start方法返回Task 我將定義插件加載任務的列表,並在每個任務完成時與Task.WhenAll檢查。 之后,您可以假定所有Start方法都已返回。

List<IPlugin> plugins = ... 
var pluginsLoadingTasks = new List<Task>();

foreach(var plugin in plugins)
{
    pluginsLoadingTasks.Add(plugin.Start());
}

// It's not necessary to check if pluginsLoadingTasks is empty, 
// because WhenAll won't throw an exception in that case
await Task.WhenAll(pluginsLoadingTasks);
// You can assume all Start methods have completed

我建議您閱讀 Task.WhenAllParallel.ForEach構造之間的區別

暫無
暫無

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

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