zoukankan      html  css  js  c++  java
  • 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 }
    View Code

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

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

    于是就做了个实验,当用下面这个语句的时候,点击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方法。

                           

  • 相关阅读:
    批处理(bat)的一些记录
    在 Docker 中已运行的 container 如何修改 run 时的 env
    Linux 的一些命令记录
    Javascript aop(面向切面编程)之around(环绕)
    dojo Provider(script、xhr、iframe)源码解析
    dojo/request模块整体架构解析
    require、module、exports dojo中的三个特殊模块标识
    CSS垂直居中总结
    Javascript图片裁切
    CSS Font知识整理总结
  • 原文地址:https://www.cnblogs.com/icbcfang/p/4398888.html
Copyright © 2011-2022 走看看