c#异步async和await
新建一个wpf程序,界面上拖入进度条和按钮控件设置进度条属性为IsIndeterminate="True"
wpf的XAML代码:
<Button Content="Button" HorizontalAlignment="Left" Margin="274,264,0,0" VerticalAlignment="Top" Width="173" Height="60" Click="Button_Click"/> <ProgressBar HorizontalAlignment="Left" Height="142" Margin="96,80,0,0" VerticalAlignment="Top" Width="562" IsIndeterminate="True" />
按钮点击事件:
private void Button_Click(object sender, RoutedEventArgs e) { WebClient ws = new WebClient(); String result=ws.DownloadString("https://gitzab.com"); MessageBox.Show(result); }
运行程序点击按钮会发现进度条卡住、按钮、窗口均无法操作,这里必须等待下载好执行页面的html字符串才能继续对这个窗口的操作,显然这里用同步的方式去做这种耗时的操作不适合.
异步实现:
private void Button_Click(object sender, RoutedEventArgs e) { //异步的方式 WebClient wc = new WebClient(); var downloadThread = new Thread(() => { var result = wc.DownloadString("https://www.bilibili.com/"); MessageBox.Show(result); }); downloadThread.Start(); }
我们希望下载网页字符串完成前不允许再次点击button按钮,修改代码如下:
private void Button_Click(object sender, RoutedEventArgs e) { DownLoadButton.IsEnabled = false; WebClient wc = new WebClient(); var downloadThread = new Thread(() => { var result = wc.DownloadString("https://www.bilibili.com/"); MessageBox.Show(result); //由于DownLoadButton按钮是在主线程中执行的,新开的线程无法操作,所以这里回到主线程中对按钮进行操作 Dispatcher.Invoke(()=> { DownLoadButton.IsEnabled = true; }); }); downloadThread.Start(); }
上述代码维护性,可读性都比较差,微软为了简化这个操作引入了async和await关键字来实现以上的操作,修改代码如下:
private async void Button_Click(object sender, RoutedEventArgs e) { var result = await Save(); MessageBox.Show(result); } public async Task<String> Save() { DownLoadButton.IsEnabled = false; var wc = new WebClient(); var result = await wc.DownloadStringTaskAsync("https://www.163.com/"); await Task.Run(()=> { File.WriteAllText("d:/result.txt",result); }); DownLoadButton.IsEnabled = true; return "Successfully saved the content"; }