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
查看全文
相关阅读:
Scrapy中的POST请求发送和递归爬取
爬虫之Scrapy框架
linux下的python3,virtualenv,Mysql,nginx,redis安装配置
Linu之linux系统基础优化和基本命令
Linux之linux基础命令2
Linux之linux基础命令
Linux之linux入门
Linux之服务器介绍
Django之content_type
Vue.js之路由系统
原文地址:https://www.cnblogs.com/furenjun/p/WinFormThreadPool.html
最新文章
git深入研究
Log4j、Log4j2的日志输出级别和配置文件详解
平安租赁
oracle基本操作
基本概念
批量数据清理
应用架构
收获,不止ORACLE
配置 C3P0 数据源
hibernate总结
热门文章
leptonica 学习笔记1
最简单的分词程序——最大匹配
MongoDB 入门之查询(find)
leptonica使用问题
跟我一起写Makefile:MakeFile介绍
[转载]常用的人脸识别数据资源
【转】ldconfig和ldd用法
简述configure、pkg-config、pkg_config_path三者的关系
【转】sublime text 2 下的Markdown写作
【转】Vim 常用命令总结
Copyright © 2011-2022 走看看