【Thread】SynchronizationContext线程间同步

在做项目的过程中,我们经常会用多线程进行处理,但是多个线程之间怎么互相通信?互相访问数据?现在小编分享两种方法

一:

  SynchronizationContext在通讯中充当传输者的角色,实现功能就是一个线程和另外一个线程的通讯。

  需要注意的是,不是每个线程都附加SynchronizationContext这个对象,只有UI线程是一直拥有的。故获取SynchronizationContext也只能在UI线程上进行SynchronizationContext context = SynchronizationContext.Current;

  那什么时候会用到呢?

  在多线程操作时往往需要切回某个线程中去工作,等完成后再切回来。

  如主UI线程中创建了一个子线程A。A中添加了委托事件。UI线程中向A线程的类注册了事件,当A线程触发事件时去修改UI上的属性如TEXT。

  这个时候往往要在UI线程向子线程注册的事件方法中使用控件的invoke方法才能访问UI线程中的控件,因为这些注册的事件(委托)方法代码虽然看似写在UI线程的Form类中,但实际上是注册在了子线程A的事件中,它们是会被子线程A触发事件时在子线程内部执行的。这样,我们不得不在主UI线程的类的注册事件方法中通过控件的Invoke方法才能访问控件,这样做十分麻烦。我们想和系统的控件事件一样,直接在注册的事件方法中访问控件。那么这个时候就可以用SynchronizationContext了。

  SynchronizationContext.Send(SendOrPostCallback d,object state);

  SynchronizationContext.Post(SendOrPostCallback d,object state);

  d 为一个没有返回值,并且具有一个Object类型传入参数的委托(SendOrPostCallback );

  state 为执行这个委托时的参数(object);

注意:

  SynchronizationContext的对象不是所有线程都被附加的,只有UI主线程会被附加。

  对于UI线程来说,是如何将SynchronizationContext这个对象附加到线程上的呢?

  在Form1 form = new Form1()之前,SynchronizationContext对象是为空,而当实例化Form1窗体后,SynchronizationContext对象就被附加到这个线程上了。

  所以可以得出答案了:当Control对象被创建的同时,SynchronizationContext对象也会被创建并附加到线程上。所以在使用时,一定要等窗体InitializeComponent(); 这个完成后 它才能得到一个不是NULL的对象.

  那么SynchronizationContext的Send()和Post()二个方法有什么区别呢?

  Send() 是简单的在当前线程上去调用委托来实现(同步调用)。也就是在子线程上直接调用UI线程执行,等UI线程执行完成后子线程才继续执行。

  Post() 是在线程池上去调用委托来实现(异步调用)。这是子线程会从线程池中找一个线程去调UI线程,子线程不等待UI线程的完成而直接执行自己下面的代码。

示例:

窗体加载,然后新建一个线程,new thread(委托)。

private void PilotageBillAuditForm_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
            System.Threading.Thread thread = new System.Threading.Thread(init);
            thread.Start();
        }
 void init()
        {
            BangdingCmbYHBZ();
            ClearData();
            SetPilotBillNoCount();
            SetPilotBillYesCount();
        }

新建立的线程和主线程之间通过synContext的post方法进行通信。

  private void SetPilotBillNoCount()
        {
            Proxy.ShipPilotClient client = new Proxy.ShipPilotClient();
            int count = client.GetPilotBillNoCount(getPilotBillNoSQL());
            client.Close();
            synContext.Post(p =>
            {
                dgv_pilotbill_no.DataSource = null;
                pageControlNo.Rcount = count;
            }, null);
        }

猜你喜欢

转载自blog.csdn.net/lnazj/article/details/79759918
今日推荐