2014-02-12 99 views
2

我有一個功能:異步和並行執行的功能

int f1(int a) 
{ 
    return a; 
} 

int f2(int a) 
{ 
    return a*2; 
} 

我想執行的功能異步並行,等待結果和總結,然後結果。我可以使用代碼

var result1 = Task.Run(() => f1(5)); 
var result2 = Task.Run(() => f2(10)); 

await Task.WhenAll(result1, result2); 

int result = result1.Result + result2.Result; 

這很酷。但什麼,如果我的功能與回調

void f1(Action<int> action, int a) 
{ 
    action.Invoke(a); 
} 

void f2(Action<int> action, int a) 
{ 
    a = a*2; 
    action.Invoke(a); 
} 

f1(result => Console.WriteLine("result1 = {0}", result), 5); 
f2(result => Console.WriteLine("result2 = {0}", result), 10); 

工作,我不能重寫這個功能,使用他人代碼此功能。在這種情況下,我可以解決我的代碼不像地獄的問題?

+1

我不確定我瞭解您的問題?這些回調將在各自的任務中同步......是你在問什麼? –

+0

我不知道如何執行這些功能,然後求和結果。我只能在回調函數中執行第二個函數。但它不是平行的。 – Alexandr

回答

5
var tcs1 = new TaskCompletionSource<int>(); 
var tcs2 = new TaskCompletionSource<int>(); 

f1((x) => { tcs1.SetResult(x); }, 5); 
f2((x) => { tcs2.SetResult(x); }, 10); 

var results = await Task.WhenAll(tcs1.Task, tcs2.Task); 
int result = results[0] + results[1]; 
+1

非常感謝! – Alexandr

3

可以使用TaskCompletionSource類來創建一個表示基於回調的異步方法完成任務(或基於事件的異步方法,或異步的任何其他非Task爲基礎的方法在那裏):

var f1CompletionSource = new TaskCompletionSource<int>(); 
var f2CompletionSource = new TaskCompletionSource<int>(); 
Task.Run(() => foo.f1(n => f1CompletionSource.TrySetResult(n), 5)); 
Task.Run(() => foo.f2(n => f2CompletionSource.TrySetResult(n), 10)); 

await Task.WhenAll(f1CompletionSource.Task, 
    f2CompletionSource.Task); 

int result = f1CompletionSource.Task.Result + 
    f2CompletionSource.Task.Result; 

目前還不清楚這裏是否要f1f2通過Task.Run被調用。你提供的方法是同步的,而不是異步的,但如果你在這裏建模的實際方法是異步執行的,那麼就不需要Task.Run

+0

非常感謝你! – Alexandr