首先我们来看一段控制台应用代码:
class Program { static async Task Main(string[] args) { System.Console.WriteLine($"Thread Id is Thread:{Thread.CurrentThread.ManagedThreadId},Is Thread Pool:{Thread.CurrentThread.IsThreadPoolThread}"); var result = await ExampleTask(2); System.Console.WriteLine($"Thread Id is Thread:{Thread.CurrentThread.ManagedThreadId},Is Thread Pool:{Thread.CurrentThread.IsThreadPoolThread}"); System.Console.WriteLine(result); Console.WriteLine("Async Completed"); } private static async Task<string> ExampleTask(int Second) { await Task.Delay(TimeSpan.FromSeconds(Second)); return $"It's Async Completed in {Second} seconds"; } }输出结果
Thread Id is Thread:1,Is Thread Pool:False Thread Id is Thread:4,Is Thread Pool:True It's Async Completed in 2 seconds Async Completed如果这段代码在WPF运行,猜猜会输出啥?
private async void Async_Click(object sender, RoutedEventArgs e) { Debug.WriteLine($"Thread Id is Thread:{Thread.CurrentThread.ManagedThreadId},Is Thread Pool:{Thread.CurrentThread.IsThreadPoolThread}"); var result= await ExampleTask(2); Debug.WriteLine($"Thread Id is Thread:{Thread.CurrentThread.ManagedThreadId},Is Thread Pool:{Thread.CurrentThread.IsThreadPoolThread}"); Debug.WriteLine(result); Debug.WriteLine("Async Completed"); } private async Task<string> ExampleTask(int Second) { await Task.Delay(TimeSpan.FromSeconds(Second)); return $"It's Async Completed in {Second} seconds"; }输出结果:
Thread Id is Thread:1,Is Thread Pool:False Thread Id is Thread:1,Is Thread Pool:False It's Async Completed in 2 seconds Async Completed 一.SynchronizationContext(同步上下文)首先我们知道async await 异步函数本质是状态机,我们通过反编译工具dnspy,看看反编译的两段代码是否有不同之处:
控制台应用:
internal class Program { [DebuggerStepThrough] private static Task Main(string[] args) { Program.<Main>d__0 <Main>d__ = new Program.<Main>d__0(); <Main>d__.args = args; <Main>d__.<>t__builder = AsyncTaskMethodBuilder.Create(); <Main>d__.<>1__state = -1; <Main>d__.<>t__builder.Start<Program.<Main>d__0>(ref <Main>d__); return <Main>d__.<>t__builder.Task; } [DebuggerStepThrough] private static Task<string> ExampleTask(int Second) { Program.<ExampleTask>d__1 <ExampleTask>d__ = new Program.<ExampleTask>d__1(); <ExampleTask>d__.Second = Second; <ExampleTask>d__.<>t__builder = AsyncTaskMethodBuilder<string>.Create(); <ExampleTask>d__.<>1__state = -1; <ExampleTask>d__.<>t__builder.Start<Program.<ExampleTask>d__1>(ref <ExampleTask>d__); return <ExampleTask>d__.<>t__builder.Task; } [DebuggerStepThrough] private static void <Main>(string[] args) { Program.Main(args).GetAwaiter().GetResult(); } }WPF:
public class MainWindow : Window, IComponentConnector { public MainWindow() { this.InitializeComponent(); } [DebuggerStepThrough] private void Async_Click(object sender, RoutedEventArgs e) { MainWindow.<Async_Click>d__1 <Async_Click>d__ = new MainWindow.<Async_Click>d__1(); <Async_Click>d__.<>4__this = this; <Async_Click>d__.sender = sender; <Async_Click>d__.e = e; <Async_Click>d__.<>t__builder = AsyncVoidMethodBuilder.Create(); <Async_Click>d__.<>1__state = -1; <Async_Click>d__.<>t__builder.Start<MainWindow.<Async_Click>d__1>(ref <Async_Click>d__); } [DebuggerStepThrough] private Task<string> ExampleTask(int Second) { MainWindow.<ExampleTask>d__3 <ExampleTask>d__ = new MainWindow.<ExampleTask>d__3(); <ExampleTask>d__.<>4__this = this; <ExampleTask>d__.Second = Second; <ExampleTask>d__.<>t__builder = AsyncTaskMethodBuilder<string>.Create(); <ExampleTask>d__.<>1__state = -1; <ExampleTask>d__.<>t__builder.Start<MainWindow.<ExampleTask>d__3>(ref <ExampleTask>d__); return <ExampleTask>d__.<>t__builder.Task; } [DebuggerNonUserCode] [GeneratedCode("PresentationBuildTasks", "4.8.1.0")] public void InitializeComponent() { bool contentLoaded = this._contentLoaded; if (!contentLoaded) { this._contentLoaded = true; Uri resourceLocater = new Uri("/WpfApp1;component/mainwindow.xaml", UriKind.Relative); Application.LoadComponent(this, resourceLocater); } } private bool _contentLoaded; }我们可以看到完全是一致的,没有任何区别,为什么编译器生成的代码是一致的,却会产生不一样的结果,我们看看创建和启动状态机代码部分的实现:
public static AsyncVoidMethodBuilder Create() { SynchronizationContext synchronizationContext = SynchronizationContext.Current; if (synchronizationContext != null) { synchronizationContext.OperationStarted(); } return new AsyncVoidMethodBuilder { _synchronizationContext = synchronizationContext }; } [DebuggerStepThrough] [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Start<[Nullable(0)] TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { AsyncMethodBuilderCore.Start<TStateMachine>(ref stateMachine); } [DebuggerStepThrough] public static void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { if (stateMachine == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.stateMachine); } Thread currentThread = Thread.CurrentThread; Thread thread = currentThread; ExecutionContext executionContext = currentThread._executionContext; ExecutionContext executionContext2 = executionContext; SynchronizationContext synchronizationContext = currentThread._synchronizationContext; try { stateMachine.MoveNext();//状态机执行代码 } finally { SynchronizationContext synchronizationContext2 = synchronizationContext; Thread thread2 = thread; if (synchronizationContext2 != thread2._synchronizationContext) { thread2._synchronizationContext = synchronizationContext2; } ExecutionContext executionContext3 = executionContext2; ExecutionContext executionContext4 = thread2._executionContext; if (executionContext3 != executionContext4) { ExecutionContext.RestoreChangedContextToThread(thread2, executionContext3, executionContext4); } } }在这里总结下:
创建状态机的Create函数通过SynchronizationContext.Current获取到当前同步执行上下文
启动状态机的Start函数之后通过MoveNext函数执行我们的异步方法