先说明一下,本人最近遇到了什么问题,就是在写写消息队列的时候,发现消息队列每次接收一个消息的时候都是创建了一个新的线程。这样就导致了消息处理的时候没有在主线程上进行,然而其中的一些步事项是要通过主线程才能操作的。这样就引出了一个子线程怎么去通知主线程要做哪些事情呢?
为了解决上面的问题我找了好的多资料,好多都是用委托,去解决了,然后我又看了我的项目通过这种beginInvoker的这种办法解决不是很好用。并不能解决的当前的问题,在这个时候我发现了SynchronizationContext对象。这个对像的用处就是可以记录一个线程的上下文然后再子线程处理完之后,要用到主要程去操作的时候可以去Post或者Send一个事件支解决,这样就很方便,代码如下:
class TestClient { private Thread workThread; private SynchronizationContext mainThreadSynContext; public TestClient()//构造函数当然是主线程执行的 { mainThreadSynContext = SynchronizationContext.Current; //在这里记录主线程的上下文 workThread = new Thread(new ThreadStart(DoWork));//创建一个新的线程 } private void OnConnected(object state)//由于是主线程的同步对象Post调用,这个是在主线程中执行的 { //这里就回到了主线程里面了 //做一些事情 } private void DoWork()//这个是workThread线程执行的 { //这儿做些事(连接什么的。。。) //这而干完了 mainThreadSynContext.Post(new SendOrPostCallback(OnConnected), null);//通知主线程 } }
注意:SynchronizationContext的对象不是所有线程都被附加的,只有UI主线程会被附加。对于UI线程来说,是如何将SynchronizationContext这个对象附加到线程上的呢?
在Form1 form = new Form1()之前,SynchronizationContext对象是为空,而当实例化Form1窗体后,SynchronizationContext对象就被附加到这个线程上了。所以可以得出答案了:当Control对象被创建的同时,SynchronizationContext对象也会被创建并附加到线程上。所有在使用时,一定要等窗体InitializeComponent(); 这个完成后 它才能得到一个不这NULL的对象。
最后SynchronizationContext的Sendt()和Post()二个方法的区别:
Send() 是简单的在当前线程上去调用委托来实现(同步调用)。也就是在子线程上直接调用UI线程执行,等UI线程执行完成后子线程才继续执行。
Post() 是在线程池上去调用委托来实现(异步调用)。这是子线程会从线程池中找一个线程去调UI线程,子线程不等待UI线程的完成而直接执行自己下面的代码。