如何使动画等待?

时间:2012-06-12 03:43:58

标签: c# async-await

很抱歉无法提供更准确的标题,但这就是我想要做的。我有一个方法foo,它将启动一些UI动画。当这些动画完成后,我想要发出完成该方法的信号。但是,我不想通过事件发信号通知,而是想制作方法awaitable。如何才能做到这一点?

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

调用代码应该能够写:

await foo();

我的实际foo比上面的插图更复杂,因为我有一系列动画,这些动画一个接一个地发生,foo应该在所有动画完成后完成。

2 个答案:

答案 0 :(得分:4)

通常,基于事件完成的事情通过使用TaskCompletionSource来“包装”。不幸的是,the example on MSDN(IMHO)过于复杂,而不仅仅是单个实例+事件。你有类似的东西:

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

在这种情况下,没有真正需要TResult,但TaskCompletionSource似乎没有非泛型版本,我不确定等效模式是什么

答案 1 :(得分: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);
    }
}

我添加了第二个条件,因为在完成事件永远不会触发的情况下,即使在动画结束后,ClockState也始终显示为活动状态。因此,这需要明确设置故事板的持续时间,但到目前为止它一直很适合我。