C# WPF中如何await等待RoutedEvent完成 等待GIF动画播放结束
实现方案
核心问题是RoutedEvent只是路由事件的全局元数据标识,本身不携带实例的事件触发状态,无法直接等待。要实现await等待事件触发,标准做法是用TaskCompletionSource将实例的事件回调包装为可等待的Task,事件触发时标记任务完成即可。
第一步:修改ShowExplosion方法
将原方法的返回值从RoutedEvent改为Task,内部为动态创建的爆炸Image控件挂载动画完成事件,事件触发时清理资源并标记任务完成:
static Task ShowExplosion(MainWindow main, Point coordinate) { TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(); Image explosion = new Image(); explosion.Width = 40; explosion.Height = 40; Canvas.SetLeft(explosion, coordinate.X - 20); Canvas.SetTop(explosion, coordinate.Y - 20); Uri resourcePath = new Uri("pack://application:,,,/Resources/GIF/Explosion2_trsp.gif"); XamlAnimatedGif.AnimationBehavior.SetSourceUri(explosion, resourcePath); XamlAnimatedGif.AnimationBehavior.SetRepeatBehavior(explosion, new System.Windows.Media.Animation.RepeatBehavior(1)); XamlAnimatedGif.AnimationBehavior.SetAutoStart(explosion, true); // 挂载动画完成路由事件 RoutedEventHandler onCompleted = null; onCompleted = (sender, args) => { // 移除事件订阅,避免内存泄漏 explosion.RemoveHandler(XamlAnimatedGif.AnimationBehavior.AnimationCompletedEvent, onCompleted); // 播放完成后移除画布上的爆炸控件 main.canvas_shots.Children.Remove(explosion); // 标记任务完成 tcs.SetResult(true); }; explosion.AddHandler(XamlAnimatedGif.AnimationBehavior.AnimationCompletedEvent, onCompleted); main.canvas_shots.Children.Add(explosion); return tcs.Task; }
第二步:修正Draw方法中的调用逻辑
删除原代码中无意义的AnimationCompletedEventArgs手动实例化代码,直接await修改后的ShowExplosion即可,修改后的Draw方法中对应片段如下:
if(i == points.Count - 1) { // 等待爆炸GIF播放完成后再继续后续逻辑 await ShowExplosion(main, current.Points.ElementAt(i)); }
注意事项
- 原代码的错误点在于仅返回了静态的路由事件标识,没有针对当前创建的Image实例订阅事件,完全没有关联动画的实际播放状态。
- 路由事件必须通过具体控件实例调用
AddHandler/RemoveHandler来挂载/卸载回调,直接操作静态RoutedEvent字段没有任何效果。 - 事件触发后必须及时移除回调、清理动态创建的控件,避免造成内存泄漏。
内容的提问来源于stack exchange,提问作者Chessmate
相关产品推荐
相关产品推荐

