.NET7 WPF中Dispatcher.InvokeAsync不同Action写法执行差异原因?
三种Dispatcher调用MainWindow.Close的写法差异解析
在.NET7环境下,由于Pipe_Disconnected事件由非UI线程触发,必须通过Dispatcher将MainWindow.Close()调度到UI线程执行,但三种写法的执行逻辑有本质区别:
可运行代码
private void Pipe_Disconnected(object sender, object e) { Application.Current.Dispatcher.InvokeAsync(() => Application.Current.MainWindow.Close()); }
这里用lambda表达式包裹逻辑,只有当Dispatcher在UI线程执行委托时,才会去获取Application.Current.MainWindow并调用Close()。访问UI元素和执行Close的操作全程在UI线程完成,符合WPF线程模型要求,因此可以正常运行。
不可运行代码(写法一)
private void Pipe_Disconnected(object sender, object e) { Application.Current.Dispatcher.InvokeAsync(Application.Current.MainWindow.Close); }
不可运行代码(写法二)
private void Pipe_Disconnected(object sender, object e) { var temp = new Action(Application.Current.MainWindow.Close); Application.Current.Dispatcher.InvokeAsync(temp); }
这两种写法的问题完全一致:在非UI线程的Pipe_Disconnected方法中,创建委托时就直接访问了Application.Current.MainWindow属性。WPF禁止非UI线程直接访问UI元素属性,此时会立即抛出跨线程访问异常,根本没机会让Dispatcher将Close操作调度到UI线程执行。
核心差异总结:lambda表达式延迟了MainWindow的获取时机,直到UI线程才执行;而直接传递Close方法的委托时,在非UI线程就提前访问了UI元素,触发了线程安全检查的异常。
内容的提问来源于stack exchange,提问作者appletree5641
相关产品推荐
相关产品推荐

