解决VS2005中,线程间不可互操作的问题,一揽子解决方案:
一、首先,定义一个类: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能提供。