2012-06-12 39 views
2

對不起,不能提供更精確的標題,但這是我想要做的。我有一個方法foo,它將啓動一些UI動畫。當這些動畫完成後,我想表示完成該方法。但是不是通過事件發信號完成,我想製作方法awaitable。如何才能做到這一點?如何讓動畫等候?

void foo() 
{ 
    // start some animations 
    storyboard.Begin(); 
    storyboard.Completed += (s, e) => { // signal that foo has completed } 
} 

調用代碼應能寫:

await foo(); 

我的實際foo比上圖中更復雜,因爲我有一系列的動畫,這接二連三發生的,並且foo是當所有動畫完成時應該完成。

回答

3

通常基於事件完成的事情通過使用TaskCompletionSource獲取'包裝'。不幸的是,the example on MSDN(恕我直言)過於複雜,而不僅僅是一個單一的事件+事件。你會碰到這樣的:

public Task Foo() 
{ 
    var tcs = new TaskCompletionSource<bool>(); 
    storyboard.Begin(); 
    storyboard.Completed += (s, e) => tcs.SetResult(true); 
    return tcs.Task; 
} 

在這種情況下,還有一個供TResult沒有真正的需要,但TaskCompletionSource不會出現具有非通用版本,我不知道什麼是等價模式將是

+0

'TaskCompletionSource'確實沒有非通用版本,如果你想返回'Task',使用'TaskCompletionSource '(可能帶註釋)可能是最好的解決方案。但這不是唯一的選擇:另一種可能性是返回自定義的等待類型。但在這種情況下這樣做會過度。 – svick

0

我最近遇到了一個情況,即Completed事件沒有按時發射,有時甚至沒有發射,即使我在調用Begin()之前設置了事件處理函數(這是大多數其他人的罪魁禍首相關的帖子我發現)。所以我正在尋找一種方法來等待動畫結束,然後以相同的方法繼續。我最終創建了下面的靜態方法,它將想要等待的故事板作爲參數。

public async static Task RunStoryboard(Storyboard Story) 
{ 
    Story.Begin(); 
    while (Story.GetCurrentState() == ClockState.Active && Story.GetCurrentTime() < Story.Duration) 
    { 
     await Task.Delay(100); 
    } 
} 

我添加了第二個條件,因爲在那裏Completed事件從來沒有發射的情況下,ClockState會始終顯示爲主動,動畫結束後還是一樣。因此,這需要明確地設定故事板的持續時間,但迄今爲止,它一直在爲我工作。