使用AsyncOperation和AsyncOperationManager时出现的问题
环境:多线程,辅助线程与主线程同步问题
问题:主线程上使用AsyncOperationManager.CreateOperation创建了一个AsyncOperation,但在调用AsyncOperation.Post一个委托函数后,那个回调函数并未转到主线程上运行,由于辅助线程不能直接操作主线程上声明的变量,导致应用程序出现异常,主界面挂掉。
调试:在Main函数中,如果在实例化主窗体之前,调用AsyncOperationManager.CreateOperation创建一个AsyncOperation时,就会出现上述问题;但如果在实例化主窗体之后,创建AsyncOperation时,则不会出现上述问题;至此,问题解决,但两者都是在主线程上创建的AsyncOperation,只是创建位置不同,为何会出现不同的结果呢?
解决:通过谷歌大神,找到这样一段描述:
WindowsFormsSynchronizationContext is internally set for the main GUI thread when you create main form of your application. Later this synchronization context is used to execute delegates on the same main GUI thread.(出处)
算是明白了,意思大概如下:创建你的应用程序主窗体后,在main GUI线程上内部设置的WindowsFormsSynchronizationContext,而后这个同步上下文才在同一个main GUI线程上执行那个回调函数。
使用Reflector看了下WindowsFormsSynchronizationContext,其构造函数:
public WindowsFormsSynchronizationContext()
{
this.DestinationThread = Thread.CurrentThread;
Application.ThreadContext context = Application.ThreadContext.FromCurrent();
if (context != null)
{
this.controlToSendTo = context.MarshalingControl;
}
}
设置controlToSendTo为当前上下文的MarshalingControl;其Post方法:
public override void Post(SendOrPostCallback d, object state)
{
if (this.controlToSendTo != null)
{
this.controlToSendTo.BeginInvoke(d, new object[] { state });
}
}
归根到底,还是使用了Control.BeginInvoke。
总结:
简单来说,主窗体未创建时,是不会得到WindowsFormsSynchronizationContext的,得到的是一个SynchronizationContext对象,那么在调用Post时,会在线程池中新起一个辅助线程去执行回调函数,这样就出现了异常:辅助线程修改主线程中声明的控件的属性。
posted on 2011-12-23 19:24 Gavin Young 阅读(537) 评论(0) 收藏 举报
 
                    
                     
                    
                 
                    
                 
                
            
         
 
         浙公网安备 33010602011771号
浙公网安备 33010602011771号