Winform界面异步初始化

来源:互联网 发布:linux文件用户权限 编辑:程序博客网 时间:2024/05/10 00:28

问题描述:

       WinForm系统在系统跳转过程中出现了长时间的卡顿现象(10s),这样长时间的界面卡顿显然是不被允许,界面跳转控制在1s以内还是可以接受的。

问题分析:

      造成这样的卡顿应该是目标页面需要初始化的资源过多造成的,分析了一下目标页面的布局,总共包含四个控件:一个ToolStripContainer,一个AxMapControl,一个ToolBar 和N多个ToolStripButton。

而这些控件都是在可视化布局视图中通过拖拽控件布局的,对应的初始化代码均在InitComponent()中完成,而这个函数是在Load之前,在跳转之前的卡顿肯定是必然的了。

解决办法:

      解决这个问题自然想到的就是延迟目标页面控件的初始化,在页面加载完成后再进行内部页面的生成。我首先采用的办法是使用多线程方法,即在Load事件响应中声明一个线程,让该线程负责后续控件的生成,但是该方法会造成下图的问题:当前线程不在单线程单元中无法实例化ActiveX控件(AxMapControl是一个ActiveX控件)。这个是因为COM对象的套间问题(套间是深入浅出COM中提到的翻译),那么将线程模型改为单套间呢?

private void SpatialMainControl_Load(object sender, EventArgs e){       Thread initThread = new Thread(new ThreadStart(InitControl));       initThread.SetApartmentState(ApartmentState.STA);       initThread.Start();}

调用 initThread.SetApartmentState(ApartmentState.STA);将当前线程修改为单套间,但是依然没用。程序报异常:在某个线程上创建的空间不能成为在另一个线程上创建的空间的父级。这个异常说明目前Winform不支持跨进程修改UI啊,看起来只能在UI进程中修改了,在主线程中加载界面但是又不能阻塞怎么办?查了资料后发现Winform的Control提供了一个异步方法BeginInvoke,根据博客http://www.fx114.net/qa-246-76092.aspx中的分析,这货其实就是将委托对应的函数地址封装了放到主线程消息队列中,由主线程调用,但是当前调用立刻返回,不会阻塞当前线程,Ok就用这个方法了。

private void SpatialMainControl_Load(object sender, EventArgs e){       BeginInvoke(new Action(InitControl));}
果然解决了问题,真是吃一堑,长一智啊。

总结:

1、负载界面布局尽量使用动态布局;

2、使用异步方法加载界面;


欢迎交流:QQ:1936856741 ; E-mail:zhaozhipeng1000@126.com

0 0
原创粉丝点击