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能提供。

  • 相关阅读:
    etymology-R
    arp与免费arp的差别,arp老化
    基于S3C2440的linux-3.6.6移植——LED驱动【转】
    《unix环境高级编程》学习笔记【原创】
    安装截图工具 Shutter【转】
    《UNIX环境高级编程第三版》apue.h等源码文件的编译安装【转】
    Ubuntu 下安装Source Insight [转]
    "makefile:5: *** missing separator. Stop."【转】
    深入浅出剖析C语言函数指针与回调函数(一)【转】
    总结与反思、理想与规划---嵌入式学习之旅【原创】
  • 原文地址:https://www.cnblogs.com/arxive/p/6675107.html
Copyright © 2011-2022 走看看