很抱歉无法提供更准确的标题,但这就是我想要做的。我有一个方法foo
,它将启动一些UI动画。当这些动画完成后,我想要发出完成该方法的信号。但是,我不想通过事件发信号通知,而是想制作方法awaitable
。如何才能做到这一点?
void foo()
{
// start some animations
storyboard.Begin();
storyboard.Completed += (s, e) => { // signal that foo has completed }
}
调用代码应该能够写:
await foo();
我的实际foo
比上面的插图更复杂,因为我有一系列动画,这些动画一个接一个地发生,foo
应该在所有动画完成后完成。
答案 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也始终显示为活动状态。因此,这需要明确设置故事板的持续时间,但到目前为止它一直很适合我。