实现等待窗体的几种方式:

下面说明了五种可以实现等待窗体的方式,其中三种给出了代码。

准备资料

安全访问控件成员

为了保证在创建控件的线程上调用控件成员,用下面的方式封装控件的属性、方法、其他自定义成员的访问。

如: winWordControl.LoadDocument()封装为:

delegate void VoidDelegate();

private void LoadDocument()

{

if (InvokeRequired)

{

Invoke(new VoidDelegate(LoadDocument));

return;

}

this.winWordControl.LoadDocument();

}

下面的代码封装了winWordControl.OpenMode=Opration

private delegate void OpenModeDelegate(Operation op);

private void OpenMode(Operation value)

{

if (InvokeRequired)

{

Invoke(new OpenModeDelegate(OpenMode), new object[] { value });

return;

}

winWordControl.OpenMode = value;

}

这些封装保证了对控件成员的访问在任何线程都是安全的。

例子说明

例子假定有三个窗体:

MainForm:

Preview preview;//Preview 是在此线程创建

Privite void SomeMethod()

{

Thread wordInit = new Thread(new ThreadStart(preview.InitWordDocControl));

wordInit.Start();

}

第二个窗体

PreviewForm:

WinWordControl winWordControl = new WinWordControl();

Private void InitWordDocControl()

{

//执行初始化加载word、实现延迟窗体

//TODO

}

第三个窗体

WaitForm:提示信息

实现方式

InitWordDocControl为了在加载word时不出现假死,必须开启新线程。
由于用到了非托管资源,最简单的方式是把托管资源(WaitForm)放在工作线程,线程结束,窗体会自动销毁,不用自己写清理代码。

第一种:ShowDialog

ShowDialog自动阻塞当前线程,这使它成为最优的解决方式。

Private void InitWordDocControl()

{

Thread thread = new Thread(new ThreadStart(Waiting));

thread.Start();

LoadDocument();

thread.Abort();//销毁线程,自动回收托管资源

}

private void Waiting()

{

//局部变量,在此线程创建,可以直接操作其成员

Wait FormWait = new Wait();

FormWait.StartPosition = FormStartPosition.CenterScreen;

FormWait.ShowDialog(); //线程等待

}

private void LoadDocument()

{

if (InvokeRequired)

{

Invoke(new VoidDelegate(LoadDocument));

return;

}

this.winWordControl.LoadDocument();

}

最简单的解决方式,利用了托管资源的优势和ShowDialog本身的特性。

第二种:Show

如果简单的修改Waiting为:

private void Waiting()

{

Wait FormWait = new Wait();

FormWait.StartPosition = FormStartPosition.CenterScreen;

FormWait.Show();       //窗体立即被销毁

}

窗体肯定会一闪而过,因为FormWait是局部变量,出了方法体就会被回收。

因此要改成下面的形式:

首先把局部变量改为字段,让他在加载类型时分配内存。其次,做如此修改后,创建Wait的线程就变成了创建Preview的线程,这样就不能直接修改此窗体属性,必须用Invoke。

private void Waiting()

{

//下面的调用都是线程安全的,内部都会判断是否是创建线程,不是会调用Invoke

CreateWait();

SetFormStartPosition(FormStartPosition.CenterScreen);

ShowWait();

}

修改:

Private void InitWordDocControl()

{

Thread thread = new Thread(new ThreadStart(Waiting));

thread.Start();

thread.Join();//阻塞调用线程,让其先执行完show

LoadDocument();

}

修改LoadDocument()

private void LoadDocument()

{

if (InvokeRequired)

{

Invoke(new VoidDelegate(LoadDocument));

return;

}

this.winWordControl.LoadDocument();

CloseWait(); //释放资源,线程自动销毁。注意也要使用线程安全的形式。

}

第三种:异步委托

本质上通过线程池中的线程执行委托方法,仍然是线程问题。但是可以用show和异步委托结合,简单的实现等待。可以看出代码比上面实现简单许多。

首先这次把加载word放到新线程中,而WaitForm在原线程。

修改:

Private void InitWordDocControl()

{

Waiting();

MethodInvoker mi = new MethodInvoker(LoadDocument);

mi.BeginInvoke(AsyncCallClose,null);//执行完委托方法,执行AsyncCallClose来关闭等待窗体。

}

private void AsyncCallClose(IAsyncResult ar)

{

FormWait.Close();

}

MethodInvoker,只是系统定义的委托,提供些许便利,更好的方式是自己定义如:

delegate void VoidDelegate();VoidDelegate 和MethodInvoker是等价的。

在这种实现中发现了下面的问题:控件成员可以不在创建控件的线程中使用!!如FormWait.Close();调用此语句的是线程池中的线程,而FormWait是在另外的线程中创建。不知道是什么原因??按照必须在创建控件线程调用成员,则会抛异常。按照许多资料,这种情况也是非法调用,但在此却没有问题?!

第四种:信号量

以前没有用过线程,遇到这个问题,首先想到的是信号量来控制线程通信。可以参考后面的资料或者我以前的文章:

http://www.cnblogs.com/bluewater/archive/2006/08/14/476720.html

第五种:Timer

本质也是线程,有同学说,他一直在VB中用Timer来模拟线程来控制时间片。应该也能实现等待窗体。

在此使用线程,主要是为了有好的用户体验,避免假死。

第一次使用线程,查了许多资料,但仍然有个问题没有解决,再写一遍,希望有人指点原因。

在这种实现中发现了下面的问题:控件成员可以不在创建控件的线程中使用!!如FormWait.Close();调用此语句的是线程池中的线程,而FormWait是在另外的线程中创建。不知道是什么原因??按照必须在创建控件线程调用成员,则会抛异常。按照许多资料,这种情况也是非法调用,但在此却没有问题?!

资料:

一系列关于线程的入门文章,非常好

http://www.yoda.arachsys.com/csharp/threads/parameters.shtml

关于UI

http://msdn.microsoft.com/msdnmag/issues/03/02/Multithreading/

关于Timer

http://msdn.microsoft.com/msdnmag/issues/04/02/TimersinNET/default.aspx

实现等待窗体的几种方式相关推荐

  1. 一起谈.NET技术,C#创建不规则窗体的几种方式

    现在,C#创建不规则窗体不是一件难事,下面总结一下:       一.自定义窗体,一般为规则的图形,如圆.椭圆等. 做法:重写Form1_Paint事件(Form1是窗体的名字),最简单的一种情况如下 ...

  2. Task_等待任务完成几种方式

    1.0 ContinueWith 在ContinueWith会得到上个任务的结果并且可以用IsFaulted判断上个任务是否出现异常! var t = Task.Run(() => { thro ...

  3. 第四节:Task的启动的四种方式以及Task、TaskFactory的线程等待和线程延续的解决方案

    一. 背景 揭秘: 在前面的章节介绍过,Task出现之前,微软的多线程处理方式有:Thread→ThreadPool→委托的异步调用,虽然也可以基本业务需要的多线程场景,但它们在多个线程的等待处理方面 ...

  4. 两种方式实现登录跳转新窗体

    两种方式实现登录跳转新窗体 直接隐藏登录窗体 显示主界面 //验证是否有此用户 int? flag = studentService.StudentLogin(userNameText.Text.Tr ...

  5. VC++等待光标的两种实现方式

    VC++等待光标的两种实现方式 有时候在做烦琐的工作时,希望鼠标处于忙状态,有两种简单的方法来实现: 1. 采用ApI函数,大多数采用此方法: BeginWaitCursor(); .....处理.. ...

  6. Winform中通过NPOI导出Excel的三种方式(HSSFWorkbook,XSSFWorkbook,SXSSFWorkbook)附代码下载

    场景 HSSFworkbook,XSSFworkbook,SXSSFworkbook区别 HSSFWorkbook: 是操作Excel2003以前(包括2003)的版本,扩展名是.xls:导出exce ...

  7. 返回ajax有几种方式,java ajax返回 Json 的 几种方式

    方式 1. : 自写代码转 Json 需要  HttpHttpServletRequest request  HttpServletResponse response 后台 : @RequestMap ...

  8. Qt开发应用程序的两种方式

    目录 案例:计算圆面积(两种方式实现) 方式一:设计器 Qt Designer实现   (20201015) 方案A:触发按钮事件(_clicked()) 方案B:触发输入编辑框事件(_textCha ...

  9. ASP.NET页面之间传递值的几种方式

    页面传值是学习asp.net初期都会面临的一个问题,总的来说有页面传值.存储对象传值.ajax.类.model.表单等.但是一般来说,常用的较简单有QueryString,Session,Cookie ...

最新文章

  1. RDKit | 分子坐标的测量和绘图
  2. 设置UIButton上面是image,下面是title
  3. 【LeetCode】0046.全排列 (递归详解)
  4. odoo10 ORM操作
  5. 图片压缩上传Thumbnailator 插件
  6. 七桥问题c语言程序数据结构,数据结构与算法学习——图论
  7. 【LeetCode】剑指 Offer 60. n个骰子的点数
  8. 腾讯员工每年写3万行代码;马斯克承认利用摄像头监视车主;Chrome 89上线实时字幕 | 极客头条...
  9. js获取image中src属性的方法语句
  10. 啊哈算法(pdf免积分下载)
  11. shell脚本日常机房巡检
  12. mac book air 外接USB无线网卡TP-LINK TL WN821N
  13. Navicat Premium15 注册出现No all pattern found! file already patched?
  14. 机器学习-有监督学习-分类算法:SVM/支持向量机【SVM:高维空间里用于二分类的超平面;支持向量:超平面附近隔离带边界上的样本】【求参数(ω,b)使超平面y(x)=Φ(x)·ω+b能最优分隔两集合】
  15. 如何通过 onstat 命令监控GBase8s数据库
  16. WP7 个人股票软件 GilStock v1.0 正式版
  17. Google中国招聘三大标准 实干、内功与人品
  18. 我是如何获取到全校同学的证件照?
  19. 谷歌FLAN-T5作者亲讲:5400亿参数,1800个任务,如何实现大语言模型“自我改进”...
  20. linux系统查看IP地址,不显示IP地址或者只显示127.0.0.1

热门文章

  1. PHP获取当前时间差8小时的问题
  2. Photoshop图像处理操作汇总
  3. 【C++】C++11 STL算法(八):对未初始化内存的操作(Operations on uninitialized memory)、C库(C library)
  4. linux 测试环境启用jar_Linux下用java -jar运行可执行jar包的方法教程
  5. 上面一个星星下面一个r_中国第一个王朝不是夏朝?山西出土一个破陶壶,上面俩字揭开谜题...
  6. 微信小程序进度条样式_微信小程序组件progress进度条解读和分析
  7. Java学习总结:31(StringBuffer类)
  8. 怎么看懂c语言程序,求讲解一下这个程序,我看了1个小时都没有看懂,
  9. 【java】兴唐第十七节课
  10. Android 活动与活动间数据传递--登录注册页面