C#笔记之 跨线程通信解决方案

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){
 //主线程操作
}

有没有觉得比委托更简单明了!

目前自己就遇到以上几种方法,也都使用过,后面遇到不同的方案也会补充。

猜你喜欢

转载自blog.csdn.net/wyl_tyrael/article/details/79708247