await/async的使用
例如,我们执行一个求和函数并把此函数执行的结果显示到UI上。我们可以如下使用:
1 private void Button_Click_2(object sender, RoutedEventArgs e) 2 { 3 txtDisplay.Text = null; 4 Display("Summation start"); 5 6 int sum = Summation(1000 * 2); 7 8 Display($"Summation result:{sum}"); 9 } 10 11 private int Summation(int n) 12 { 13 int sum = 0; 14 for (int i = 0; i < n; i++) 15 { 16 sum += i; 17 System.Threading.Thread.Sleep(1); 18 } 19 20 return sum; 21 }
但此处代码有一个问题,会阻塞UI线程,为了解决此问题,对求和函数启动一个Task任务,等任务执行完毕,把求和结果返回即可:
1 private void Button_Click(object sender, RoutedEventArgs e) 2 { 3 txtDisplay.Text = null; 4 Display("Summation 0 start"); 5 6 int sum= SummationAnsyc0(1000*2); 7 8 Display($"Summation 0 result:{sum}"); 9 } 10 11 private int SummationAnsyc0(int n) 12 { 13 Task<int> task = Task<int>.Factory.StartNew(() => 14 { 15 int sum = 0; 16 for (int i = 0; i < n; i++) 17 { 18 sum += i; 19 System.Threading.Thread.Sleep(1); 20 } 21 22 return sum; 23 }); 24 25 return task.Result; 26 }
但执行此函数,我们发现实际上还会阻塞UI主线程,这是因为Task任务返回Result结果的时候,若Task尚未结束,就会等待Task完成,而 return task.Result 在UI主线程上返回,因此会阻塞UI线程。
那么,如何实现既要返回所需的结果,又不会阻塞当前线程呢?
答案是使用await/async,需.NET4.5以上版本支持(C#5.0以上)。
1 private async void Button_Click_1(object sender, RoutedEventArgs e) 2 { 3 txtDisplay.Text = null; 4 5 Display("Summation 1 start"); 6 7 int sum= await TaskAnsyc1(1000 * 3); 8 9 Display($"Summation 1 result:{sum}"); 10 } 11 12 private async Task<int> TaskAnsyc1(int n) 13 { 14 Task<int> task = Task.Factory.StartNew(() => 15 { 16 int sum = 0; 17 for (int i = 0; i < n; i++) 18 { 19 sum += i; 20 System.Threading.Thread.Sleep(1); 21 } 22 23 return sum; 24 }); 25 26 return await task; 27 }
执行结果会按下图正常执行,同时不会阻塞UI线程