【转】WPF_UI线程问题
1.由于其他线程拥有此对象,因此调用线程无法对其进行访问 (The calling thread cannot access this object because a different thread owns it)
WPF中大多数控件都继承自DispatcherObject,也就拥有Dispatcher属性,Dispatcher有两个方法:Invoke和BeginInvoke,用来对外开放访问这个Dispatcher所属的线程所拥有的控件的机会。
myTextBlock.Dispatcher.Invoke(new Action(delegate{myTextBlock.Text = "Info"; }));
2.调用线程必须为 STA,因为许多 UI 组件都需要
在 WPF 中,只有创建 DispatcherObject 的线程才能访问该对象。 例如,一个从主 UI 线程派生的后台线程不能更新在该 UI 线程上创建的 Button 的内容。 为了使该后台线程能够访问 Button 的 Content 属性,该后台线程必须将此工作委托给与该 UI 线程关联的 Dispatcher。 使用 Invoke 或 BeginInvoke 来完成此操作。 Invoke 是同步操作,而 BeginInvoke 是异步操作。 该操作将按指定的 DispatcherPriority 添加到 Dispatcher 的事件队列中。
Invoke 是同步操作;因此,直到回调返回之后才会将控制权返回给调用对象
避免方法如下:
A.
public delegate void DeleFunc(); public void Func() { //使用ui元素 }
线程函数中做如此调用即可
System.Windows.Application.Current.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,new DeleFunc(Func));
B.
Thread NetServer = new Thread(new ThreadStart(NetServerThreadFunc)); NetServer .SetApartmentState(ApartmentState.STA); NetServer .IsBackground = true; NetServer.Start();
线程函数中做如此调用即可
System.Windows.Threading.Dispatcher.Run();
示例如下:
1 public partial class Window1 : Window 2 { 3 private delegate void DoTask(); 4 public Window1() 5 { 6 InitializeComponent(); 7 Thread t = new Thread(new ThreadStart(Start)); 8 t.Start(); 9 } 10 private void Start() 11 { 12 System.Windows.Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new DoTask(DoMyTask)); 13 } 14 private void DoMyTask() 15 { 16 //在此执行你的代码 17 } 18 }