转自原文 多线程环境下的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能提供。

多线程环境下的UI异步操作的更多相关文章

  1. Asp.Net在多线程环境下的状态存储问题

    在应用开发中,我们经常需要设置一些上下文(Context)信息,这些上下文信息一般基于当前的会话(Session),比如当前登录用户的个人信息:或者基于当前方法调用栈,比如在同一个调用中涉及的多个层次 ...

  2. C#多线程环境下调用 HttpWebRequest 并发连接限制

    C#多线程环境下调用 HttpWebRequest 并发连接限制 .net 的 HttpWebRequest 或者 WebClient 在多线程情况下存在并发连接限制,这个限制在桌面操作系统如 win ...

  3. C++多线程环境下的构造函数

    多线程的环境里,我们总不可避免要使用锁.于是一个常见的场景就是: class ObjectWithLock { private: std::mutex mtx_; SomeResType shared ...

  4. SQLite在多线程环境下的应用

    文一 SQLite的FAQ里面已经专门说明,先贴出来.供以后像我目前的入门者学习. (7) 多个应用程序或者同一个应用程序的多个例程能同时存取同一个数据库文件吗? 多进程可以同时打开同一个数据库,也可 ...

  5. 多线程环境下非安全Dictionary引起的“已添加了具有相同键的项”问题

    问题: 代码是在多线程环境下,做了简单的Key是否存的判断, 测试代码如下: public class Program { static Dictionary<string, Logger> ...

  6. HttpClient在多线程环境下踩坑总结

    问题现场 在多线程环境下使用HttpClient组件对某个HTTP服务发起请求,运行一段时间之后发现客户端主机CPU利用率呈现出下降趋势,而不是一个稳定的状态. 而且,从程序日志中判断有线程处于han ...

  7. 单例模式在多线程环境下的lazy模式为什么要加两个if(instance==null)

    刚才在看阿寻的博客”C#设计模式学习笔记-单例模式“时,发现了评论里有几个人在问单例模式在多线程环境下为什么lazy模式要加两个if进行判断,评论中的一个哥们剑过不留痕,给他们写了一个demo来告诉他 ...

  8. 一个由单例模式在多线程环境下引发的 bug

    问题症状 HTTP 日志系统,老是出现日志信息覆盖的情况.比如同时调用 A 接口和 B 接口,B 接口请求响应信息变成了 A 接口请求响应相关信息.这个问题在并发量大的情况下越来越严重. 问题初步分析 ...

  9. 你是否听说过 HashMap 在多线程环境下操作可能会导致程序死循环?

    作者:炸鸡可乐 原文出处:www.pzblog.cn 一.问题描述 经常有些面试官会问,是否了解过 HashMap 在多线程环境下使用时可能会发生死循环,导致服务器 cpu 100% 的线上故障? 关 ...

随机推荐

  1. Python中的collections模块

    Python中内置了4种数据类型,包括:list,tuple,set,dict,这些数据类型都有其各自的特点,但是这些特点(比如dict无序)在一定程度上对数据类型的使用产生了约束,在某些使用场景下效 ...

  2. 【javascript】如何延迟加载JavaScript(Google推荐的代码)

    下面是Google推荐的代码.这些代码应被放置在</body>标签前(接近HTML文件底部)<script type="text/javascript">f ...

  3. php pdo调用SQLServer存储过程无法获取返回结果

    确定存储过程写的没问题,php调用后,跟踪了语句,也是没问题,就是获取不到返回结果.折腾,搞定. 较之前明确了1. 调用存储过程传参的写法: 2. 获取返回结果集的方法 参考: http://blog ...

  4. GCD基础

    一.GCD介绍 1.what is GCD? Grand Central Dispatch 中枢调度器.用很简单的方式实现了极为复杂繁琐的多线程编程.异步执行任务的技术之一.   2.GCD存在于li ...

  5. Redis中关于Hash键的一些问题

    Hash键存在的意义: 1.Hash键可以将信息凝聚在一起,而不是直接分散的存储在整个Redis中,这不仅方便了数据管理,还可以尽量避免一定的误操作: 2.避免键名冲突: 3.减少内存占用.(最重要的 ...

  6. Redis缓存的设计、性能、应用与数据集群同步

    Redis缓存的设计.性能.应用与数据集群同步 http://youzhixueyuan.com/design-performance-and-application-of-redis-cache.h ...

  7. jquery 给新增的addClass 使用css样式

    假如有一个情况,当导航url找不到相同的地址,就会出现找不到地址,高亮当前导航不出现 解决 办法 记得使用文档载入完成后执行的函数. 因为 .current 是 addClass 新增的class $ ...

  8. pyqtree

    pyqtree module API Documentation Classes class Index The top spatial index to be created by the user ...

  9. FastAdmin 如何升级?

    FastAdmin 如何升级? 官方推荐使用 git 升级 FastAdmin. 升级 FastAdmin 核心代码 git stash git pull git stash pop 更新前端组件 比 ...

  10. qt 把整形数据转换成固定长度字符串(转)

    QString ToStr(int number, int size){ return QString("%1").arg(number, size, 10, QChar('0') ...