2012-04-01 169 views
8

我正在爲自己的使用打包一個庫。爲了獲得某個財產,我需要等待一個事件。我試圖將其包裝到異步調用中。將事件轉換爲異步調用

基本上,我想轉

void Prepare() 
{ 
    foo = new Foo(); 
    foo.Initialized += OnFooInit; 
    foo.Start(); 
} 
string Bar 
{ 
    return foo.Bar; // Only available after OnFooInit has been called. 
} 

進入這個

async string GetBarAsync() 
{ 
    foo = new Foo(); 
    foo.Initialized += OnFooInit; 
    foo.Start(); 
    // Wait for OnFooInit to be called and run, but don't know how 
    return foo.Bar; 
} 

這怎麼可能最好地完成?我可以循環等待,但我試圖找到更好的方法,如使用Monitor.Pulse(),AutoResetEvent或其他。

回答

23

這就是TaskCompletionSource進場的地方。這裏沒有足夠的空間容納新的async關鍵字。例如:

Task<string> GetBarAsync() 
{ 
    TaskCompletionSource<string> resultCompletionSource = new TaskCompletionSource<string>(); 

    foo = new Foo(); 
    foo.Initialized += OnFooInit; 
    foo.Initialized += delegate 
    { 
     resultCompletionSource.SetResult(foo.Bar); 
    }; 
    foo.Start(); 

    return resultCompletionSource.Task; 
} 

樣品使用(花式異步)

async void PrintBar() 
{ 
    // we can use await here since bar returns a Task of string 
    string bar = await GetBarAsync(); 

    Console.WriteLine(bar); 
} 
+0

我想這個功能可以被包裹在一個異步函數?或者只是給函數添加異步並返回resultCompletionSource.Task.Result;這會導致它等待? – 2012-04-01 09:38:36

+0

這可以封裝在異步函數中,現在更新示例 – Polity 2012-04-01 09:39:20

+0

剛注意到,System.Threading.Tasks在我的目標平臺Windows Phone 7上不可用。有其他選擇嗎? (已發現[this](http://www.nuget.org/packages/System.Threading.Tasks),但我想盡量減少依賴關係) – 2012-04-01 11:37:29