本文编写于 697 天前,最后修改于 697 天前,其中某些信息可能已经过时。
问题展示
大多数初次在C#中进行WPF程序写作的程序员,当代码涉及UI操作时可能会出现错误:
调用线程无法访问此对象,因为另一个线程拥有该对象
可以看到,我在MainWindow
中创建了一个文本框对象outputbox
,在使用如下代码进行操作时,返回该错误
this.outputbox.AppendText(msg);
this.outputbox.AppendText("\r\n");
究其原因,在WPF程序中,UI线程和后台线程分离,后台线程不能直接访问和修改UI层。WinForm按理说应该也是同样的线程分离方法,但是我在编写WinForm程序的时候没有出现这个问题,很奇怪。
解决方案
想要解决这个问题也很简单。在WPF程序中,引入了Dispacher
用于管理线程工作项队列,可以简单把Dispacher
理解为一个调度器。由于UI是由主线程创建的,而后台线程是子线程,所以后台线程不能直接访问UI对象,这时候只需要调用UI对象的Dispacher.BeginInvoke
就可以把操作扔回UI线程执行,这样就不存在线程冲突的问题了。
this.outputbox.Dispatcher.BeginInvoke(new Action(() => { outputbox.AppendText(msg); }));
this.outputbox.Dispatcher.BeginInvoke(new Action(() => { outputbox.AppendText("\r\n"); }));
在将原代码改成上述代码后,程序顺利运行,没有再次出现错误。
碎碎念
发现了一个神奇的事情,在使用Fody以后线程冲突问题消失,原因未知...