zoukankan      html  css  js  c++  java
  • 多线程环境下的UI异步操作

    转自原文 多线程环境下的UI异步操作

    解决VS中,线程间不可互操作的问题,一揽子解决方案:

    一、首先,定义一个类:SetControlProperty

    using System.Reflection;
    
    using System;
    
    using System.Windows.Forms;
    
    namespace Ways.Utils
    
    {
    
        class SetControlProperty
    
        {
    
            delegate void SetValueDelegate(Object obj, Object val, Object[] index);
    
            public SetControlProperty(Control ctrl, String propName, Object val)
    
            {
    
                PropertyInfo propInfo = ctrl.GetType().GetProperty(propName);
    
                Delegate dgtSetValue = new SetValueDelegate(propInfo.SetValue);
    
                ctrl.Invoke(dgtSetValue, new Object[3] { ctrl, val, null });
    
            }
    
        }
    
    }

    二、在要操作Form中调用

    本例中,此调用是由一通讯事件引发的:

    void testcommand_EndStatusEvent(object sender, EventArgs e)
    
    {
    
        new SetControlProperty(label4, "Text", "END");
    
        new SetControlProperty(button1, "Enabled", true);
    
    } 

    三、 最简化,但却不安全的方案

    Control.CheckForIllegalCrossThreadCalls = false;

    试过了,在.net compact framework中,不可用!

    四、.NETCF中的解决方案,来源:.NET Compact Framework 多线程环境下的UI异步刷新

    在进行WinCe或者Windows Mobile开发中,通常需要把一些任务提交给工作线程(Worker Thread)完成,当worker thread 线程发生状态变更的时候需要通知UI进程刷新UI,比如一个网络连接程序,Worker Thread线程负责管理WiFi,GPRS或者3G等连接,当连接状态发生改变时候,Worker Thread把更新状态通知UI Thread,而UI Thread更新UI通知用户。

    这里常常有个疑问,为什么Worker Thread不直接更新UI,这样更简单直接和明了。但是UI刷新不是线程安全(Thread Safe)的,所以Worker Thread直接更新UI会抛出"cross-thread operation not valid"异常。所以需要Thread Safe的通知方法,下面演示更新短语(Message)的方法如下:
    Worker Thread Class

    class ConnectionMgr
    
    {
    
        //Delegate for Message
    
        public delegate void MessageEventHandler(string msg);
    
        public event MessageEventHandler MessageEvent; 
    
        //the delegate of Message event
    
        private void MessageHandler(string msg)
    
        {
    
            MessageEventHandler messageEvent = MessageEvent;
    
            if (messageEvent != null)
    
            {
    
                messageEvent(msg);
    
            }
    
        }
    
        private void ConnectHandler()
    
        {
    
            MessageHandler("Connected");
    
        }
    
        private void DisconnectHandler()
    
        {
    
            MessageHandler("Disconnected");
    
        }
    
    } 

    在Worker Thread定义delegate和event供UI Thread注册。当状态发生改变是调用该delegate。

    UI Thread

    public partial class Form1 : Form
    
    {
    
        public Form1()
    
        {
    
            //register the connect event
    
            ConnectionMgr.Instance.MessageEvent += MessageEvent;
    
        } 
    
        private void MessageEvent(string msg)
    
        {
    
            SafeWinFormsThreadDelegate d = new SafeWinFormsThreadDelegate(ShowMessage);
    
            Invoke(d, new object[] { msg} ); 
    
        } 
    
        public delegate void SafeWinFormsThreadDelegate(string msg);
    
        private void ShowMessage(string msg)
    
        {
    
            eventText.Text = msg;
    
        }
    
    } 

    UI Thread通过delegate订阅连接事件,当连接状态发生改变的时候,Worker Thread异步调用void MessageEvent(string msg)。这里调用Invoke方法来进行线程安全的调用。调用参数使用Object[]来传递,因此程序可以传递任何信息,UI可以呈现任何信息只要Worker Thread能提供。

  • 相关阅读:
    Oracle查询错误分析:ORA-01791:不是SELECTed表达式
    Java中DESKeySpec类
    linux发布项目
    mac下搭建cocos2d-x2.2.1版本android编译环境教程
    使用Eigen求解线性方程组
    视觉SLAM十四讲课后答案-ch1
    costmap_2d: obstacle_layer中关于激光雷达障碍物清除不干净的解决
    ch4 激光的前端配准算法一 —— ICP方法
    Project 'cv_bridge' specifies '/usr/include/opencv' as an include dir, which is not found.
    ch3 传感器数据处理II: 激光雷达运动畸变去除
  • 原文地址:https://www.cnblogs.com/arxive/p/6675107.html
Copyright © 2011-2022 走看看