當我們遇到一些異步執行又無法等待時的邏輯,比如動畫的執行。
而業務上又需要等待邏輯的完成,再去處理後續的操作。這時需要轉成異步方法
如下,同步執行一個動畫後,再輸出日志:
1 private async void TaskCompleteSourceAwait_OnClick(object sender, RoutedEventArgs e)
2 {
3 bool isCompleted = await AwaitByTaskCompletionAsync(new Storyboard() { Duration = new Duration(TimeSpan.FromSeconds(2)) });
4 Debug.WriteLine($"TaskCompleteSourceAwait_OnClick end:{isCompleted}");
5
通過TaskCompletionSource如何轉化為異步方法,并等待動畫完成?
1 /// <summary>
2 /// 執行動畫
3 /// </summary>
4 /// <param name="storyboard"></param>
5 /// <returns></returns>
6 public static async Task<bool> AwaitByTaskCompletionAsync(Storyboard storyboard)
7 {
8 var taskCompletionSource = new TaskCompletionSource<bool>();
9
10 Debug.WriteLine("Storyboard start");
11
12 storyboard.Completed += OnStoryboardCompleted;
13 storyboard.Begin();
14
15 void OnStoryboardCompleted(object sender, EventArgs e)
16 {
17 Debug.WriteLine("Storyboard end");
18 storyboard.Completed -= OnStoryboardCompleted;
19 taskCompletionSource.SetResult(true);
20 }
21 return await taskCompletionSource.Task;
22
測試效果:
參考資料:
- 深入了解 WPF Dispatcher 的工作原理(PushFrame 部分)
- 使用任務簡化異步程式設計
- Async/Await異步程式設計中的最佳做法
同步轉異步
- C# 同步轉異步 TaskCompletionSource
- C# 同步轉異步 AutoResetEvent
異步轉同步
- C# 異步轉同步 PushFrame
- C# 異步轉同步 TaskCompletionSource
死鎖
- C# 死鎖 Task/AutoResetEvent
- C# 死鎖 TaskCompletionSource
作者:唐宋元明清2188