Windows 窗体多线程
当我们在编写一个需要长时间运行的程序时(如数学计算,执行数据库命令,访问WebService)
常常将它们写在一个组件中,让他们在后台运行.从而不影响Windows界面的显示和界面上的交
互操作.但我们有时还是感到不怎方便,如我们不能直接应用winForm里定义的变量等.那么在
UI进程中能否直接执行长时间运行的程序,而不影响UI进程呢?
下面的示例将解决这个问题.
本例利用多线程从长时间运行的操作(计算fbnc数列(n>36))中分离出用户界面 (UI),
以将用户的后续输入传递给辅助线程(CalHandler,showDel)以调节其行为与用户界面元素
进行交互,从而实现稳定而正确的多线程处理的消息传递方案。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
namespace AsynchCalcPi
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
Form2.calComplete += new CalHandler(Form2_calComplete);
}
void Form2_calComplete(string strTemp)
{
//为了对调用者屏蔽与此 UI 线程有关的线程安全通信信息,
//ShowCalcResult 方法在此 UI 线程上通过 Control.BeginInvoke 方法使用 showDel 给自己发送消息。
//Control.BeginInvoke 异步队列为 UI 线程提供服务,并且不等待结果就继续运行。
if(!bClose )
this.BeginInvoke(new showDel(showRes ),strTemp );
}
int times = 1;
private void showRes(string strTemp)
{
times += 1;
this.richTextBox1.AppendText("," + strTemp);
this.progressBar1.Value = iStep * times%100;
if (FinishFlag)
{
//timer1.Enabled = false;
MessageBox.Show(strTemp);
}
}
private delegate void showDel(string stemp);
private void button1_Click(object sender, EventArgs e)
{
try
{
j = Int32.Parse(this.textBox_Num.Text.Trim());
iStep = 100 / j;
if (j < 1)
return;
}
catch
{
MessageBox.Show("请在文本框内输入数字字符");
return;
}
for (int i = 0; i < j; i++)
this.richTextBox1.AppendText(this.ComputeFibonacci(i).ToString() + ",");
}
private long ComputeFibonacci(int n)
{
//' The parameter n must be >= 0 and <= 91.
//' Fib(n), with n > 91, overflows a long.
if (n < 0 || n > 91)
{
MessageBox.Show("value must be >= 0 and <= 91", "n");
}
long result = 0;
if (n < 2)
result = 1;
else
{
result = ComputeFibonacci(n - 1) + ComputeFibonacci(n - 2);
}
return result;
}
public int AddInterlink(int i)
{
if (i <= 0)
return 0;
else if (i > 0 && i <= 2)
return 1;
else return AddInterlink(i - 1) + AddInterlink(i - 2);
}
private void button2_Click(object sender, EventArgs e)
{
try
{
j = Int32.Parse(this.textBox_Num.Text.Trim());
iStep = 100 / j;
if (j < 1)
return;
}
catch
{
MessageBox.Show("请在文本框内输入数字字符");
return;
}
for (int i = 0; i < j; i++)
this.richTextBox1.AppendText(this.AddInterlink(i).ToString() + ",");
}
private void button3_Click(object sender, EventArgs e)
{
try
{
j = Int32.Parse(this.textBox_Num.Text.Trim());
iStep = 100 / j;
if (j < 1)
return;
}
catch
{
MessageBox.Show("请在文本框内输入数字字符");
return;
}
ComputeFibonacciDel calcFbnc = new ComputeFibonacciDel(this.ComputeFibonacci);
calcFbnc.BeginInvoke(j, callBack, null);
}
//实时显示通知服务
private long ShowCalcResult(int n)
{
long result1 = 0;
for (int i = 0; i < n; i++)
{
result1 = this.ComputeFibonacci(i);
//委托calComplete 由辅助线程用于向 UI 线程回传消息,通常是有关长时间运行的操作的最新进度。
calComplete(result1.ToString() );
}
return result1;
}
//定义计算过程中用于传递消息的委托
public delegate void CalHandler(string strTemp);
//定义事件
public static event CalHandler calComplete;
//定义委托 进行异步计算Fibonacci数列
private delegate long ComputeFibonacciDel(int n);
//定义引用在异步操作完成时调用的回调方法.用以在计算完成后取得返回值和当前状态.
AsyncCallback callBack = new AsyncCallback(ShowResult);
private static bool FinishFlag = false;
static void ShowResult(IAsyncResult ar)
{
// Asynchronous Callback method.
// Obtains the last parameter of the delegate call.
int value = Convert.ToInt32(ar.AsyncState);
// Obtains return value from the delegate call using EndInvoke.
AsyncResult aResult = (AsyncResult)ar;
ComputeFibonacciDel temp = (ComputeFibonacciDel)aResult.AsyncDelegate;
long result = temp.EndInvoke(ar);
FinishFlag = true;
calComplete("当前状态代号:" + value.ToString() + " " + "计算后的返回结果:" + result.ToString());
}
int i = 0;
private void timer1_Tick(object sender, EventArgs e)
{
i += 1;
i = i % 100;
this.progressBar1.Value = i;
}
int j = 0;
int iStep = 1;
ComputeFibonacciDel calcFbnc;
private void button4_Click(object sender, EventArgs e)
{
FinishFlag = false;
//停止进度条的自动滚动.让进度条根据当前进度显示
this.timer1.Enabled = false;
this.progressBar1.Value = 0;
try
{
j= Int32.Parse(this.textBox_Num.Text.Trim());
iStep = 100 / j ;
if (j < 1)
return;
}
catch
{
MessageBox.Show("请在文本框内输入数字字符");
return;
}
//ComputeFibonacciDel,用于捆绑要传递给(从线程池中分配的)辅助线程上的ShowCalcResult 的参数。
//当用户决定要计算 fbnc数列 时,事件处理程序将创建此委托的一个实例。
//此工作通过调用 BeginInvoke 在线程池中进行排队。该委托实际上是由 UI 线程用于向辅助线程传递消息。
calcFbnc = new ComputeFibonacciDel(this.ShowCalcResult );
IAsyncResult aResult= calcFbnc.BeginInvoke(j,callBack , null);
//已在callBack方法中写出,此处不再写此方法.
/**/////Wait for the call to complete
//aResult.AsyncWaitHandle.WaitOne();
//long callResult = calcFbnc.EndInvoke(aResult);
}
bool bClose = false;
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
bClose = true;
}
//参考资料:
//http://www.microsoft.com/china/MSDN/library/archives/library/dnforms/html/winforms08162002.asp
}
}
源码:AsynchCalcFbnc
Windows 窗体多线程相关推荐
- 使用C#制作Windows窗体应用,实现一个微端下载器功能(多线程/断点续传/微端/下载器)
文章目录 一.前言 二.最终运行效果 三.Demo工程下载 四.工程类型 五.工程结构 六.多线程下载核心代码 一.前言 在PC端的QQ游戏大厅下载游戏的时候,我们会发现很多游戏都自己做了微端下载器, ...
- 理解Windows窗体和WPF中的跨线程调用
你曾开发过Windows窗体程序,可能会注意到有时事件处理程序将抛出InvalidOperationException异常,信息为" 跨线程调用非法:在非创建控件的线程上访问该控件" ...
- C# Windows 窗体编程入门详解
C# Windows 窗体编程入门详解 基于Web的B/S架构应用程序近年来确实非常流行,B/S易于部署.易于维护的特点使Web应用程序开发得到了前所未有的发展.但是,Web应用程序的缺点是,它们有时 ...
- 列举窗体控制台应用程序中的3中控件_今天来点枯燥的,Visual C#的Windows窗体运行过程...
我们上一期只是在windows窗体上放了三个控件,并编写了一段小程序,实现了触发窗体上的按钮,使得标签上的内容改变,并能够结束运行当中的程序: 然而,我们在编写代码窗口时,windows窗体自动嵌入了 ...
- VS2010 win32项目windows窗体程序 向导生成代码解析
目录: 1.Win32项目的windows窗体程序的向导生成了如下代码 2.手工生成代码如下 3.当消息队列中没有消息需要处理,我们可以利用这段时间处理我们自己的任务 1.Win32项目的window ...
- Windows窗体的所有菜单
简介仅仅使用一行简单的程序,你就能够使你的Windows窗体的所有菜单和上下文菜单具有office2003的菜单外观.同样地,你也可以只用一行程序,就能为你的菜单加上漂亮的图标.本文实现的是一个具有该 ...
- (转)SplitContainer 控件(Windows 窗体)
1.可以将 Windows 窗体 SplitContainer 控件看作是一个复合体,它是由一个可移动的拆分条分隔的两个面板.当鼠标指针悬停在该拆分条上时,指针将相应地改变形状以显示该拆分条是可移动的 ...
- windows窗体继承问题
窗体继承什么时候用的到呢?当我们使用三层架构来编写我们的cs程序时,我们的U层大部分是windows窗体.这个时候如果我们有一些公共变量,或者是一个窗体需要使用另一个窗体的数据.或者是有一些用于判断的 ...
- windows服务守护进程bat脚本、windows窗体守护进程bat脚本
线上运行的windows服务和窗体服务程序经常挂掉,只能从windows日志中找到报了底层错误,问题无法定位,目前的办法是在服务器上运行守护进程 window服务守护进程 @echo off titl ...
最新文章
- 【读书笔记】iOS-网络-解析响应负载
- 手动启动“远程过程调用”服务时,出现错误信息1058
- 我的Ubuntu9.10安装与配置100
- 企业内部信息化项目管理之我所见
- Zookeeper基于Java 访问-节点权限设置
- 关于同步时间——hadoop
- c语言写入文件后换行,关于文件操作,碰到空格就换行
- 【零基础学Java】—Scanner类的使用( 十)
- c++ 深度拷贝和浅度拷贝
- k8s mysql 查询_MySql | 为什么大家都在说 Select * 效率低
- sql server2008密钥,sql server 2008 r2 序列号密钥
- 使用Xcode真机调试时没有任何问题,但是当打包成ipa文件安装时,有接口访问不到后台信息
- Word 连续使用格式刷
- c语言中ipv6地址比较大小,ipv6地址处置
- 算法系列——寻找峰值 (Find Peak Element)
- 什么?Python的多进程居然比单进程慢?
- 4 基于matplotlib的python数据可视化——导入Excel数据批量制作柱形图
- 星座运势查询微信小程序源码 周公自定义解梦源码
- 2017年8月1日,星期二
- SourceTree使用小技巧
热门文章
- 蓝松短视频经验分享----抠图和动画设计
- 向安卓模拟器中添加文件
- 数学图形(1.2)Sin曲线
- 安卓关于fragment切换后继续运行的问题!
- Tesorflow源代码安装方式以及错误的解决方法
- .NET MVC Filter异常处理
- 异步多线程(五)多线程异常处理
- ssh遇到port 22:No route to host问题的解决方法
- webgl(three.js)实现室内定位,楼宇bim、实时定位三维可视化解决方案——第五课
- 如何通过终端快速删除文件和目录(bash shell)[关闭]