WPF线程问题

今天看书上写的一个例子,

1  private void AddMessage(string formatString,
2            params string[] parameters)
3         {
4           Dispatcher.BeginInvoke(new Action(
5                () => WatchOutput.Items.Insert(
6                   0, string.Format(formatString, parameters))));
7 }

Dispatcher.BeginInvoke是啥玩意,为啥要这么做呢?为啥不直接用

1 WatchOutput.Items.Insert(0, string.Format(formatString, parameters));

于是就做了个实验,当用下面这个语句的时候,点击Watch按钮的时候,没有问题,但当我修改对应文件的属性时,触发事件,此时报错。

未处理InvalidOperationException“由于其他线程拥有此对象,因此调用线程无法对其进行访问。

上网查了下,原来是线程问题,WPF应用程序一般有两个线程,一个用于处理呈现(渲染UI),一个用来管理UI。呈现线程有效地隐藏在后台进行,而UI线程则接受输入、处理事件、绘制屏幕以及运行应用程序代码。

那为啥上面会出现这个问题呢?点击watch,没有问题,但当修改文件属性等操作时,就会出问题。这是因为有些事件处理函数,当事件被触发时,代码执行到事件处理函数里面的时候,执行代码的线程往往不是主线程,而出于对UI控件的保护,由UI进程创建的控件,其它线程是不能访问UI线程里的东西的。

通过下面能看到,执行事件时,是另外一个线程。

1)当点击Watch!按钮,触发click事件,此时的线程是主线程(UI线程)

2)当修改文件属性,触发created\changed等事件时,会创建一个新的工作线程。

注意:这里并不是所有的事件处理函数都会创建新的线程,从上面的例子就能看出来。

那既然只有主线程可以修改UI ,其它线程应该如何与用户交互呢?其它线程可以请求UI线程代表他执行操作,也就是通过向dispatcher中注册工作项来完成,dispatcher提供两个注册工作项的方法:invoke(同步)和Begininvoke(异步)。

从上面的例子看到,为了能向界面中添加文本,向dispather中注册了事件(采用lamda表达式)。

在我们用的系统中,也用到了Invoke:在显示next business时。在主线程中通过ParameterizedThreadStart创建一个新的进程。在这个进程中要修改界面上的内容,就只能调用invoke方法。

时间: 2024-11-05 13:07:08

WPF线程问题的相关文章

WPF 线程中异常导致程序崩溃

原文:WPF 线程中异常导致程序崩溃 一般我们WPF中都加全局捕获,避免出现异常导致崩溃. Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException; AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException)

WPF线程——BackgroundWorker

在WPF中第二个常用的线程处理方式就是BackgroundWorker. 以下是BackgroundWorker一个简单的例子. public partial class MainWindow : Window { /// <summary> /// 后台worker /// </summary> BackgroundWorker worker = new BackgroundWorker(); public MainWindow() { InitializeComponent()

WPF 线程 Dispatcher

WPF 应用程序从两个线程开始: 一个用于处理呈现 一个用于管理 UI 呈现线程有效地隐藏在后台运行,而UI线程则接收输入.处理事件.绘制屏幕以及运行应用程序代码. 大多数应用程序都使用一个 UI 线程,但在某些情况下,最好使用多个线程.我们将在后面举例说明这一点. UI 线程对一个名为 Dispatcher 的对象内的工作项进行排队. Dispatcher基于优先级选择工作项,并运行每一个工作项,直到完成.每个UI线程都必须至少有一个Dispatcher,并且每个 Dispatcher 都只能

WPF线程&mdash;&mdash;Dispatcher

使用WPF开发时经常会遇上自己建立的线程需要更新界面UI内容,从而导致的跨线程问题. 异常内容: 异常类型:System.InvalidOperationException 异常描述: "System.InvalidOperationException"类型的未经处理的异常在 WindowsBase.dll 中发生 其他信息: 调用线程无法访问此对象,因为另一个线程拥有该对象. 在WPF中最简便的解决此问题的方法就是使用Dispatcher. 1.最便捷的使用Dispatcher th

wpf 线程

一.线程概述:[引用MSDN] 通常,WPF 应用程序从两个线程开始:一个用于处理呈现,一个用于管理 UI.呈现线程有效地隐藏在后台运行,而 UI 线程则接收输入.处理事件.绘制屏幕以及运行应用程序代码.大多数应用程序都使用一个 UI 线程,但在某些情况下,最好使用多个线程.我们将在后面举例说明这一点. UI 线程对一个名为 Dispatcher 的对象内的工作项进行排队.Dispatcher 基于优先级选择工作项,并运行每一个工作项,直到完成.每个 UI 线程都必须至少有一个 Dispatch

WPF线程

WPF中的线程使用 简介 但凡涉及到图形界面,往往的设计都是不支持或者不推荐使用多个线程操作界面内容.而且通常会有一个专门的线程调度器来处理任务线程和界面线程的问题.下面提供两个两个方案. 使用Dispatcher.BeginInvoke 这个方法简单暴力适合小工作量的修改一些界面内容.使用Dispatcher.BeginInvoke()会将代码安排为调度程序的一个任务. 步骤 使用Thread新建并开始一个线程 在新建的线程处理函数中需要修改界面的时候获取界面的dispatcher 使用Dis

wpf 线程与界面线程

Thread thread = new Thread(new ThreadStart(() =>        {            VisualTarget visualTarget = new VisualTarget(hostVisual);            var control = new UserControl1();            control.Arrange(new Rect(new Point(), content.RenderSize));        

WPF 线程开启等待动画

public static Dictionary<string, object> Dic = new Dictionary<string, object>();//定义一个字典类型的接受窗体信息 public static void AwaitAnimation(bool isStart = true) { if (isStart == true) { Thread t = new Thread(() => { Pmtoload sw = new Pmtoload(); Di

从0 开始 WPF MVVM 企业级框架实现与说明 ---- 第一讲 WPF中 windows消息机制

谈到桌面应用程序,我们第一反应就是它的消息机制是怎么处理的,那么我们就先聊聊这个windows消息机制 谈起“消息机制”这个词,我们都会想到Windows的消息机制,系统将键盘鼠标的行为包装成一个Windows Message,然后系统主动将这些Windows Message派发给特定的窗口,实际上消息是被Post到特定窗口所在线程的消息队列,应用程序的消息循环再不断的从消息队列当中获取消息,然后再派发给特定窗口类的窗口过程来处理,在窗口过程中完成一次用户交互. 其实,WPF的底层也是基于Win