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

Windows 窗体多线程相关推荐

  1. 使用C#制作Windows窗体应用,实现一个微端下载器功能(多线程/断点续传/微端/下载器)

    文章目录 一.前言 二.最终运行效果 三.Demo工程下载 四.工程类型 五.工程结构 六.多线程下载核心代码 一.前言 在PC端的QQ游戏大厅下载游戏的时候,我们会发现很多游戏都自己做了微端下载器, ...

  2. 理解Windows窗体和WPF中的跨线程调用

    你曾开发过Windows窗体程序,可能会注意到有时事件处理程序将抛出InvalidOperationException异常,信息为" 跨线程调用非法:在非创建控件的线程上访问该控件" ...

  3. C# Windows 窗体编程入门详解

    C# Windows 窗体编程入门详解 基于Web的B/S架构应用程序近年来确实非常流行,B/S易于部署.易于维护的特点使Web应用程序开发得到了前所未有的发展.但是,Web应用程序的缺点是,它们有时 ...

  4. 列举窗体控制台应用程序中的3中控件_今天来点枯燥的,Visual C#的Windows窗体运行过程...

    我们上一期只是在windows窗体上放了三个控件,并编写了一段小程序,实现了触发窗体上的按钮,使得标签上的内容改变,并能够结束运行当中的程序: 然而,我们在编写代码窗口时,windows窗体自动嵌入了 ...

  5. VS2010 win32项目windows窗体程序 向导生成代码解析

    目录: 1.Win32项目的windows窗体程序的向导生成了如下代码 2.手工生成代码如下 3.当消息队列中没有消息需要处理,我们可以利用这段时间处理我们自己的任务 1.Win32项目的window ...

  6. Windows窗体的所有菜单

    简介仅仅使用一行简单的程序,你就能够使你的Windows窗体的所有菜单和上下文菜单具有office2003的菜单外观.同样地,你也可以只用一行程序,就能为你的菜单加上漂亮的图标.本文实现的是一个具有该 ...

  7. (转)SplitContainer 控件(Windows 窗体)

    1.可以将 Windows 窗体 SplitContainer 控件看作是一个复合体,它是由一个可移动的拆分条分隔的两个面板.当鼠标指针悬停在该拆分条上时,指针将相应地改变形状以显示该拆分条是可移动的 ...

  8. windows窗体继承问题

    窗体继承什么时候用的到呢?当我们使用三层架构来编写我们的cs程序时,我们的U层大部分是windows窗体.这个时候如果我们有一些公共变量,或者是一个窗体需要使用另一个窗体的数据.或者是有一些用于判断的 ...

  9. windows服务守护进程bat脚本、windows窗体守护进程bat脚本

    线上运行的windows服务和窗体服务程序经常挂掉,只能从windows日志中找到报了底层错误,问题无法定位,目前的办法是在服务器上运行守护进程 window服务守护进程 @echo off titl ...

最新文章

  1. 【读书笔记】iOS-网络-解析响应负载
  2. 手动启动“远程过程调用”服务时,出现错误信息1058
  3. 我的Ubuntu9.10安装与配置100
  4. 企业内部信息化项目管理之我所见
  5. Zookeeper基于Java 访问-节点权限设置
  6. 关于同步时间——hadoop
  7. c语言写入文件后换行,关于文件操作,碰到空格就换行
  8. 【零基础学Java】—Scanner类的使用( 十)
  9. c++ 深度拷贝和浅度拷贝
  10. k8s mysql 查询_MySql | 为什么大家都在说 Select * 效率低
  11. sql server2008密钥,sql server 2008 r2 序列号密钥
  12. 使用Xcode真机调试时没有任何问题,但是当打包成ipa文件安装时,有接口访问不到后台信息
  13. Word 连续使用格式刷
  14. c语言中ipv6地址比较大小,ipv6地址处置
  15. 算法系列——寻找峰值 (Find Peak Element)
  16. 什么?Python的多进程居然比单进程慢?
  17. 4 基于matplotlib的python数据可视化——导入Excel数据批量制作柱形图
  18. 星座运势查询微信小程序源码 周公自定义解梦源码
  19. 2017年8月1日,星期二
  20. SourceTree使用小技巧

热门文章

  1. 蓝松短视频经验分享----抠图和动画设计
  2. 向安卓模拟器中添加文件
  3. 数学图形(1.2)Sin曲线
  4. 安卓关于fragment切换后继续运行的问题!
  5. Tesorflow源代码安装方式以及错误的解决方法
  6. .NET MVC Filter异常处理
  7. 异步多线程(五)多线程异常处理
  8. ssh遇到port 22:No route to host问题的解决方法
  9. webgl(three.js)实现室内定位,楼宇bim、实时定位三维可视化解决方案——第五课
  10. 如何通过终端快速删除文件和目录(bash shell)[关闭]