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
转载于:https://www.cnblogs.com/furenjun/archive/2006/08/07/WinFormThreadPool.html