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
  • 相关阅读:
    600+ 道 Java面试题及答案整理(2021最新版)
    Spring Boot + Web Socket 实现扫码登录,这种方式太香了!!
    小团队适合引入 Spring Cloud 微服务吗?
    Netty 通道怎么区分对应的用户?
    软件开发打败了 80 %的程序员
    一个最简单的消息队列,带你理解 RabbitMQ!
    厉害了,Netty 轻松实现文件上传!
    Netty 是如何解决 TCP 粘包拆包的?
    图解 Git,一目了然!
    面试官:谈谈分布式一致性机制,我一脸懵逼。。
  • 原文地址:https://www.cnblogs.com/furenjun/p/WinFormThreadPool.html
Copyright © 2011-2022 走看看