2015-09-04 23 views
0

我說叫一個接口:扇出使用異步中的WebAPI計算/等待

interface IExecutor { 
    String Name { get; } 
    Task<int> Execute(); 
} 

而且它的兩個實現(細節是不相關的,你可以假設方法都標有異步和工作如預期) 。每個實現需要2-3秒的時間來運行,並將有2到5次執行IExecutor

我有一個控制器需要運行所有執行程序並將結果作爲ExecutorResult對象返回。 ExecutorResult是:

class ExecutorResult { 
    int Result; // assume usual get n set 
    String ExecutorName; 
} 

理想情況下,這應該發生在扇出方法中。

我已經想到了以下方法:

List<Task<int>> tasks = new List<Task<int>>(); 
foreach(var executor in executors) { 
    tasks.Add(executor.Execute()); 
} 

var results = Task.WhenAll(tasks); 

我有這種方法的問題是,我不能確定這是否是在ASP的WebAPI應用的最佳實踐。另外 - 給我想返回結果對象 - 其中結果需要一個執行器的名稱和來自執行上述解決方案的int結果不作爲for循環的外部工作我不再有權訪問每個的名稱屬性遺囑執行人。

那麼,什麼是這種方法的最佳實踐(再 - 給一個Web API應用程序,而不是一個控制檯應用程序)

+0

作爲最佳實踐,你應該命名爲execute()方法ExecuteAsync() –

回答

2

你已經是最佳實踐。你在做什麼是異步併發,最好用Task.WhenAll完成。

注意,代碼:

List<Task<int>> tasks = new List<Task<int>>(); 
foreach(var executor in executors) { 
    tasks.Add(executor.Execute()); 
} 
var results = Task.WhenAll(tasks); 

可以簡化爲:

var results = Task.WhenAll(executors.Select(e => e.Execute())); 

儘管使用List<Task>無數的例子,你實際上並沒有建立起來一個明確的。

1

如果我理解正確的話,你要找的somethng這樣的:

var tasks = new List<Task<ExecutorResult>>(); 
foreach (var executor in executors) 
{ 
    tasks.Add(((Func<IExecutor, Task<ExecutorResult>>)(
     async (e) => new ExecutorResult 
     { 
      ExecutorName = e.Name, 
      Result = await e.Execute() 
     }))(executor)); 
} 

var results = Task.WhenAll(tasks); 

OR,以下斯蒂芬顯然建議:

var results = Task.WhenAll(
    from executor in executors 
    select ((Func<IExecutor, Task<ExecutorResult>>)(
     async (e) => new ExecutorResult 
     { 
      ExecutorName = e.Name, 
      Result = await e.Execute() 
     }))(executor)) 
    ); 
+0

有一個編譯錯誤:無法轉換lambda表達式鍵入「System.Threading.Tasks.Task 」,因爲它不是一個委託類型 –

+0

對不起。糾正。 –

1

這爲我工作:

public class Executor : IExecutor 
{ 
    public String Name { get; set;} 

    public async Task<int> Execute() 
    { 
     Console.WriteLine("Executing " + Name); 
     await Task.Delay(3000); 
     Console.WriteLine("Finished Executing " + Name); 
     return 0; 
    } 
} 
public async Task<ExecutorResult> Execute(IExecutor executor) 
{ 
    return new ExecutorResult { ExecutorName = executor.Name, 
           Result = await executor.Execute() }; 
} 

public async Task MainAsync() 
{ 
    var executors = new List<IExecutor> 
    { 
     new Executor { Name = "Executor1" }, 
     new Executor { Name = "Executor2" }, 
     new Executor { Name = "Executor3" } 
    }; 

    List<Task<ExecutorResult>> tasks = new List<Task<ExecutorResult>>(); 

    foreach(var executor in executors) 
    { 
     tasks.Add(Execute(executor)); 
    } 

    var results = await Task.WhenAll(tasks); 
} 

void Main() 
{ 
    MainAsync().Wait(); 
}