• 多线程环境下的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能提供。

  • 相关阅读:
    143、Java内部类之访问方法中定义的参数或变量
    142、Java内部类之在普通方法里面定义内部类
    141、Java内部类之实例化外部类对象
    140、Java内部类之实例化内部类对象
    139、Java内部类之使用this访问外部类属性
    138、Java内部类之访问内部类的私有属性
    137、Java内部类之把内部类放到外部
    136、Java的内部类
    135、Java中的静态块,构造方法和构造块
    134、Java中的构造方法和构造块
  • 原文地址:https://www.cnblogs.com/arxive/p/6675107.html
Copyright © 2020-2023  润新知