Winform界面异步初始化
2015-08-03 10:03
821 查看
问题描述:
WinForm系统在系统跳转过程中出现了长时间的卡顿现象(10s),这样长时间的界面卡顿显然是不被允许,界面跳转控制在1s以内还是可以接受的。
问题分析:
造成这样的卡顿应该是目标页面需要初始化的资源过多造成的,分析了一下目标页面的布局,总共包含四个控件:一个ToolStripContainer,一个AxMapControl,一个ToolBar 和N多个ToolStripButton。
而这些控件都是在可视化布局视图中通过拖拽控件布局的,对应的初始化代码均在InitComponent()中完成,而这个函数是在Load之前,在跳转之前的卡顿肯定是必然的了。
解决办法:
解决这个问题自然想到的就是延迟目标页面控件的初始化,在页面加载完成后再进行内部页面的生成。我首先采用的办法是使用多线程方法,即在Load事件响应中声明一个线程,让该线程负责后续控件的生成,但是该方法会造成下图的问题:当前线程不在单线程单元中无法实例化ActiveX控件(AxMapControl是一个ActiveX控件)。这个是因为COM对象的套间问题(套间是深入浅出COM中提到的翻译),那么将线程模型改为单套间呢?
调用 initThread.SetApartmentState(ApartmentState.STA);将当前线程修改为单套间,但是依然没用。程序报异常:在某个线程上创建的空间不能成为在另一个线程上创建的空间的父级。这个异常说明目前Winform不支持跨进程修改UI啊,看起来只能在UI进程中修改了,在主线程中加载界面但是又不能阻塞怎么办?查了资料后发现Winform的Control提供了一个异步方法BeginInvoke,根据博客http://www.fx114.net/qa-246-76092.aspx中的分析,这货其实就是将委托对应的函数地址封装了放到主线程消息队列中,由主线程调用,但是当前调用立刻返回,不会阻塞当前线程,Ok就用这个方法了。
总结:
1、负载界面布局尽量使用动态布局;
2、使用异步方法加载界面;
欢迎交流:QQ:1936856741 ; E-mail:zhaozhipeng1000@126.com
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
相关文章推荐
- Linux 软件包管理
- 数据库连接错误---------
- 驱动编程学习笔记之IO处理
- poj 1655 Balancing Act 【树形DP 求树的重心】
- 关于github上一个可拓展和折叠的测试demo源码详解
- hdu 1452 happy 2004
- Angular Js ng-repeat指令
- H.264解码器原理
- HTML5与搜索引擎优化[转载]
- 从智能电视开始,PPTV与Letv全线开战?
- uva820 最大流模板题
- 南邮 OJ 1009 2的N次方
- hdoj-1864-最大报销额【动态规划】
- 机电行业如何进行信息化建设
- H.264编码器原理
- H.264量化参数QP和量化步长Qstep
- C#将字节数组加到List中
- xampp终端启动
- yum仅下载RPM包不安装
- adb shell am 的用法