DotNet编程-星光伴我行

滴滴真谛 水滴石穿

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

                       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
posted on 2006-08-07 13:22  DotNet编程  阅读(1567)  评论(0编辑  收藏  举报