浅析.Net 在 winform及wpf中涉及界面交互的多线程类的封装
来源:互联网 发布:ibm服务器监控软件 编辑:程序博客网 时间:2024/05/20 05:23
我们在开发客户端程序时,经常要用到多线程
而我们知道, .Net中从线程安全的考虑,对控件改变的调用要通过Invoke, beginvoke来进行,这就涉及怎么进行工作线程与界面的互操作。
本文以一个简单的应用为例,探讨多线程的封装性,我们的主要目的是让一个类能同时适wpf及winform对多线程的要求
现在假定程序里,有一个多线程的业务处理逻辑,如下:
Thread work = new Thread(new ThreadStart(run));
work.Start();
//……其他代码
void run (){
//这里有一部分要改变界面显示的代码
}
在最直观的设计中,我们是这样考虑的:
1.声明一个委托(为了从简,这里不考虑有各种参数的情况:
2.将用户界面交互的代码装在一个单独的函数中:
//改变界面显示
}
3.在线程中(这里先以winform为例)用Invoke或BeginInvoke调用这个函数
为了从简,我们只考虑Invoke
//….
this.Invoke(new foo(Foo));
//….
}
现在,我们的下一步工作是要封装这个Work类,使他在其他的winform程序中也可以方便的调用。这样,我们主要有两部分工作要做:
a.工作线程的提取
b.界面逻辑的分割
最直接的方法是这样:
class Work{
private Thread work;
public Work(){
work= new Thread(new ThreadStart(run);
}
public Begin(){
work.Start();
}
public event foo Foo;
void run (){
//这里有一部分要改变界面显示的代码
if(Foo!=null)
Foo();
}
}
这样,界面上的代码变成了这个样子:
Work = new Work(this);
Work.Foo+= new foo(FooFunction);
Work.Begin()
到此,我们已经将多线程逻辑与界面逻辑分开了,但是现在有一个问题,就是我要在FooFuction中调用Invoke
即
this.Invoke(new Foo(fooFunction));
}
fooFunction(){
//界面处理程序
}
于是,每次复用这个逻辑,我们都要反复的自己写这个Invoke,很麻烦,于是考虑进一步的改进,即,将当前Control作为一个成员封装至Work类中,即:
class Work{
private Control Owner ;
private Thread work;
public Work(Control owner){
work= new Thread(new ThreadStart(run);
Owner=owner;
}
public Begin(){
work.Start();
}
public event foo Foo;
void run (){
//这里有一部分要改变界面显示的代码
if(Foo!=null)
if(Ownner!=null)
Ownner.Invoke(Foo);
else
Foo();
}
}
这样,界面 上的代码就要整洁多了,现在我们不用在界面中调用 Invoke了:
Work = new Work();
Work.Foo+= new foo(FooFunction);
Work.Begin()
//other code ...
FooFuction(){
//更新界面
}
现在,我们已经完成了一个多线程类的封闭,它有很好的封闭性和可读性,但是,新的问题来了,即,我要把它移植到 wpf程序中,本来很完美的工作类,现在他面临如下问题:
1.不与wpf程序兼容,我得自己在程序中写对应wpf的Invoke
2.运行时要依靠Control类,即我要正常使用他,还得在wpf程序中添加winform的DLL才可以
因此,我们要进行如下工作,以使我们的Work类看着很完美
1.脱离Control类的依赖
2.能同时完美的支持winform 和wpf用户程序;
显然,这里面最重要的就是要如何处理这段代码 :
if(Foo!=null)
if(Ownner!=null)
Ownner.Invoke(Foo);
else
Foo();
考虑到我们对Control的引用只是为了调用它的Invoke ,于是,可以将Invoke提一个接口 :
void Invoke (delegate method);
public object Parent;
}
这样,我们只需将Work类中的Owner从Control变为IWorkHost,其他代码不用改变,剩下的工作就好办了:
我们可以把对windows.forms引用从Work所在的工程移掉,然后,加一个DLL工程WinformHost ,引用 Work类所在工程
声明一个类WinformHost来实现IWorkHost
private Control parent;
public object Parent{get{return parent;}}
public WinformHost(Control parent){
parent = parent;
}
public void Invoke (delegate method){
parent.Invoke(method);
}
类似的,增加用于WPF的WPFWorkHost
private Dispatcher parent;
public object Parent{get{return parent;}}
public WPFHost(Control parent){
parent = parent;
}
public void Invoke (delegate method){
parent.Invoke(method);
}
这样,当在winform中使用Work类时,代码变成:
Work.Foo+= new foo(FooFunction);
Work.Begin()
当在 wpf程序中使用 work类时,代码变成:
Work.Foo+= new foo(FooFunction);
Work.Begin()
总结:
我们在这个文章里依次做了如下的工作:
1.将一个多线程的逻辑加到winform中
2.将这个多线程封装到单独的类
3.改进这个逻辑使他同时适应winform和wpf
这里用到到模式,应该是适配器模式,其实这个应用场景和很多复用封装的场景相类似,只不过多线程在 winform和wpf中是经常讨论的问题,用这个问题来解释这种封装,我觉得会好一些。
- 浅析.Net 在 winform及wpf中涉及界面交互的多线程类的封装
- WinForm控件与WPF控件的交互
- WinForm控件与WPF控件的交互
- WinForm控件与WPF控件的交互
- WPF界面添加WinForm的Webbrowser控件
- Winform中长时间处理时良好的交互界面呈现_多线程
- 在WPF中添加WINFORM控件的方法
- WPF 中 的多线程
- .NET漫游指南-007-WPF中多线程调用界面控件
- unity与wpf, winform双向交互的方法
- 多线程之winform界面的更新
- WPF -- Winform中弹出WPF窗体不能在文本框中输入的解决方案
- WinForm与WPF互操作,在WPF的TextBox中无法输入文字
- 多线程涉及的问题
- 在WinForm中,设置Visio控件的界面布局
- 在winform界面的菜单栏和工具栏中插入分界线
- 在WPF的用户线程中更新UI界面
- 在WPF的用户线程中更新UI界面
- Linux学习笔记 (02) 文件处理命令
- class UserInputHandler
- javascript程序应写在什么地方
- 水晶报表内功心法
- junit4中的参数化测试
- 浅析.Net 在 winform及wpf中涉及界面交互的多线程类的封装
- opencv不能读视频问题解决
- 整合cocos2d API文档到XCode中
- Poj 2251 Dungeon Master
- 动态链接库dll 静态链接库lib 动态导入库lib
- Android日记之2012/01/16
- DLL入门浅析(1)——如何建立DLL
- Android中添加Options Menu,按MENU键无反应
- 音乐播放器截图(skinMagic)