## 使用 TaskScheduler 配置任务的执行 本节新建了一个WPF项目,用以观察异步时界面的响应效果。 页面代码: ```xml <Window x:Class="Recipe4_9.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Recipe4_9" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Grid> <TextBlock Name="ContentTextBlock" HorizontalAlignment="Left" Margin="44,134,0,0" VerticalAlignment="Top" Width="425" Height="40" /> <Button Content="Sync" HorizontalAlignment="Left" Margin="45,190,0,0" VerticalAlignment="Top" Width="75" Click="ButtonSync_Click"/> <Button Content="Async" HorizontalAlignment="Left" Margin="165,190,0,0" VerticalAlignment="Top" Width="75" Click="ButtonAsync_Click"/> <Button Content="Async OK" HorizontalAlignment="Left" Margin="285,190,0,0" VerticalAlignment="Top" Width="75" Click="ButtonAsyncOK_Click"/> </Grid> </Window> ``` 后台代码: ``` public MainWindow() { InitializeComponent(); } private void ButtonSync_Click(object sender, RoutedEventArgs e) { ContentTextBlock.Text = string.Empty; try { // string result = TaskMethod(TaskScheduler.FromCurrentSynchronizationContext()).Result; // 同步调用,当前用户界面会被冻结,在任务执行完毕前无法响应任何操作 // TaskMethod中的Task线程无法UI线程中的控件ContentTextBlock,导致发生异常 string result = TaskMethod().Result; // 该赋值不会被执行到 ContentTextBlock.Text = result; } catch (Exception ex) { // 出异常时显示异常消息 ContentTextBlock.Text = ex.InnerException.Message; } } private void ButtonAsync_Click(object sender, RoutedEventArgs e) { ContentTextBlock.Text = string.Empty; Mouse.OverrideCursor = Cursors.Wait; // 异步执行Task,用户界面不会被冻结,任务执行期间界面仍然可以响应用户操作 // 但是仍然会发生异常 Task<string> task = TaskMethod(); task.ContinueWith( t => { ContentTextBlock.Text = t.Exception.InnerException.Message; Mouse.OverrideCursor = null; }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.FromCurrentSynchronizationContext()); } private void ButtonAsyncOK_Click(object sender, RoutedEventArgs e) { ContentTextBlock.Text = string.Empty; Mouse.OverrideCursor = Cursors.Wait; // 将UI线程任务调度程序(TaskScheduler.FromCurrentSynchronizationContext())提供给了任务 Task<string> task = TaskMethod(TaskScheduler.FromCurrentSynchronizationContext()); task.ContinueWith( t => Mouse.OverrideCursor = null, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); } private Task<string> TaskMethod() { return TaskMethod(TaskScheduler.Default); } private Task<string> TaskMethod(TaskScheduler scheduler) { Task delay = Task.Delay(TimeSpan.FromSeconds(5)); return delay.ContinueWith(t => { string str = $"Task is running on a thread id {Thread.CurrentThread.ManagedThreadId}. " + $"Is thread pool thread: {Thread.CurrentThread.IsThreadPoolThread}"; ContentTextBlock.Text = str; return str; }, scheduler); } ``` 执行结果: 1. 单击Sync按钮:界面无法响应任何操作,异步处理发生异常  2. 单击Async按钮:界面可以响应操作,但是异步处理仍然发生异常  3. 单击Async OK按钮:界面可以响应操作,异步处理没有发生异常  Loading... 版权声明:本文为博主「佳佳」的原创文章,遵循 CC 4.0 BY-NC-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://www.liujiajia.me/2017/7/28/csharp-multi-threading-04-tpl-09-use-task-scheduler 提交