zoukankan
html css js c++ java
Windows 窗体多线程
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
查看全文
相关阅读:
SPRING IN ACTION 第4版笔记-第九章Securing web applications-008-使用非关系型数据库时如何验证用户(自定义UserService)
[转]苹果商店审核规则,你触犯了哪一条?
Xcode itunes完美打包api方法
Swift中构造器的继承和重写
Swift中类的两段式构造(类的构造过程)
Swift中的便利构造器和构造器链
iOS在UITableViewController里使用UISearchDisplayController报错"[UISearchResultsTableView dequeueReusableCellWithIdentifier:forIndexPath:]"
Swift缩水版MJExtension
构造器相关
可选链
原文地址:https://www.cnblogs.com/furenjun/p/WinFormThreadPool.html
最新文章
二叉排序树
Linux启动一个服务后,服务的某个文件所在的目录下出现类似:systemd-private.xxxxxx的目录
mariadb启动报错:[ERROR] Can't start server : Bind on unix socket: Permission denied
Linux运维之——每日小技巧,获取网站请求数的前20个IP
Linux运维之——每日小技巧,使用awk命令截取每行的指定列数据
MySQL面试题36道
Innodb存储引擎的缓存命中率计算
iptables实战演练
MySQL报错:error1130
linux操作系统基础讲解
热门文章
安装Tidb数据库出现SSD硬盘IOPS不到40000的错误
HeadFirst设计模式之命令模式
HeadFirst设计模式之单例模式
HeadFirst设计模式之门面模式
HeadFirst设计模式之工厂模式
HeadFirst设计模式之装饰者模式
HeadFirst设计模式之观察者模式
HeadFirst设计模式之策略模式
SPRING IN ACTION 第4版笔记-第九章Securing web applications-010-拦截请求
SPRING IN ACTION 第4版笔记-第九章Securing web applications-009-拦截请求()
Copyright © 2011-2022 走看看