【转】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 }

 

posted @ 2018-03-31 15:48  死鱼眼の猫  阅读(451)  评论(0编辑  收藏  举报