C# 跨线程通信解决方案
Android和C#之间来回跑是真的累,虽然两者语法有很多相似的地方,Adnroid跨线程通信还是有很多方案的,Handler用得最多,C#也不例外,以下算是自己根据网上的资料结合自己在项目中使用情况的总结:
1、 最简单粗暴的
在相应窗体的构造方法里面加入下面一句代码:
Control.CheckForIllegalCrossThreadCalls = false;
意思就是编译运行时不检查线程之间访问的冲突,子线程可以随时更新UI,虽然很方便,但是安全性却很低,很容易造成数据的不一致性,比如你子线程A更新了某个控件的值,此时线程B又去更新了这个控件的值 ,这就不能保证事物的一致性,后果很严重!所以还是不建议使用,也不明白微软为啥还保留这个。
2、利用delegate和invoke
//声明一个委托
private delegate void DelegateClick(/**参数列表*/);
//委托执行的方法
private void initUI(/**参数列表*/){
if (/*你要更新的控件 比如Label*/ label1.InvokeRequired)
{
// 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它
DelegateClick mDele=new DelegateClick(initUI);
this.label1.Invoke(mDele, new object[] { /*参数*/});
} else
{
this.label1.Text = /*参数*/;
}
}
public Form(){
......
//开启线程
Thread t=new Thread(new ThreadStart(initUI));//执行更新Ui的方法
t.Start();
//也可以是这样
Thread t=new Thread(new ParameterizedThreadStart(/*方法*/));
t.Start(/*参数*/);
}
上面使用的是Invoke,也可以使用BeginInvoke,前者是同步的,要等待工作线程完成,而后者是异步的。
3、使用BackgroundWorker
//实例化一个BackgroundWorker
BackgroundWorker bgWorker=new BackgroundWorker();
bgWorker.DoWork += bgWorker_DoWork;//工作线程
bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted;//主线程
//工作线程
void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
//后台耗时等
}
void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//执行更新UI的操作
}
个人感觉BackgroundWorker跟Android里面的AsyncTask的工作原理应该是一样的。
4、SynchronizationContext
最开始自己使用最多的就是委托来实现线程通信,后面发现了这个SynchronizationContext。意思是 提供在各种同步模型中传播同步上下文的基本功能。
private SynchronizationContext sync;
public Form(){
......
// 原意是获取当前线程的同步上下文 我的理解是获取当前线程的托管吧
sync= SynchronizationContext.Current;
Thread t=new Thread(new ThreadStart(doInBackground));
t.Start();
}
......
//这是工作线程
private void doInBackground(){
......
//后台工作完成后需要更新UI或者回到主线程
sync.Post(new SendOrPostCallback(InitUI),/*参数*/);//发送异步消息
//或者
sync.Send(new SendOrPostCallback(InitUI),/*参数*/);//发送同步消息
}
private void InitUI(object obj){
//主线程操作
}
有没有觉得比委托更简单明了!
目前自己就遇到以上几种方法,也都使用过,后面遇到不同的方案也会补充。