解决C#界面假死问题

       前几天做ArcEngine二次开发时需要连接ArcSDE数据库,感觉连接ArcSDE的时间有点长,想着在连接ArcSDE之前跳出一个带等待动画的界面等待ArcSDE的链接,于是写了如下代码:

private void buttonX1_Click(object sender, EventArgs e)//button1在主窗口中
{
     Waitting waitting = new Waitting();
     waitting.show();//form2加载时有等待动画 
     ConnectSDE();//运行时间5秒左右 
     waitting.hide();//等待界面消失,回到主界面
}
       

       后来在运行的时候发现waitting中的动画根本无法运行,后来百度了才知道是线程阻塞问题。当一个WinForm程序在事件函数中进行IO操作、网络操作或耗CPU大的操作时,窗体会出现明显的卡顿现象。原因在于窗体的消息循环被耗时的操作停住了,UI线程被阻塞。在相关操作没有完成之前,用户不能对窗体进行任何的操作,包括关闭应用程序,此时用户看到的该窗体会出现无法响应,而我form2的动画效果就这样被阻塞了。


解决C#界面假死问题_第1张图片

       此时我们自己解决问题的思路肯定是——能不能将阻塞线程的操作在另外一个线程中执行,这样就不会堵塞UI线程。

       然而从另外一个线程操作windows窗体上的控件,就会和主线程产生竞争,造成不可预料的结果。因此windowsGUI编程有一个规则,就是只能通过创建控件的线程来操作控件的数据。

       好在因此Control类实现了ISynchronizeInvoke接口,提供了Invoke和BeginInvoke方法来提供让其它线程更新GUI界面控件的机制。

       两者区别是:Invoke,需要等待委托的方法执行返回后才执行下面的代码;begininvoke则不需要。

       所以最后的解决方案如下:

解决C#界面假死问题_第2张图片

        private void buttonX1_Click(object sender, EventArgs e)  
        {
            Waitting waitting = new Waitting();  
            waitting.Show();  
            Task.Factory.StartNew(() => // 将阻塞线程的操作在另外一个线程中执行,这样就不会堵塞UI线程。   
            {   
                ConnectSDE(); //运行时间5s左右
                MessageBox.Show("连接SDE数据库成功", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);  
                waitting.BeginInvoke((Action)waitting.Close);//BeginInvoke方法返回UI线程更新UI界面控件的机制。   
            });  
        }

       这样程序在ConnectSDE( )方法运行的过程中不会阻塞主线程,Waitting界面的动画也可以展示了:

       解决C#界面假死问题_第3张图片

       ConnectSDE( )方法运行结束,弹窗提示。确定后BeginInvoke方法返回UI线程关闭等待窗口

解决C#界面假死问题_第4张图片

         总结就是:对于UI阻塞,可以将阻塞线程的操作放在另外一个线程执行;而对于跨线程调用,可以使用invoke()或者BeginInvoke() 来解决问题。

         一直没提异步操作的原因是我个人不太理解线程操作与异步操作的区别。我个人的理解是:异步与同步是相对的,同步即阻塞,即做A的时候做不了B;AB可以同时做互不干扰就叫异步。而为了实现异步,可以利用多线程。异步是目的,多线程是手段。BeginInvoke、EndInvoke这些异步操作应该是.NET精心封装好的,未必与多线程有关。这样就可以理解百度百科异步词条百度词条—异步。异步不需要占用额外线程这句话了。

       同样的,我个人感觉异步是相对的。在上面的解决方案中,如果使用了Invoke同步方法(实际上这里用Invoke也没啥区别),会在Task中阻塞线程,然而Invoke会回调UI线程的委托,即线程中同步,线程间异步,听上去是不是很玄乎。。。









你可能感兴趣的:(C#,ArcEngine开发笔记)