• Application.DoEvents()和多线程


    如何使用Application.DoEvents() 和 多线程?

    首先将以下代码放到Button事件里面:

    private void btnStart_Click(object sender, EventArgs e)
    {
    for (int q = 0; q < 100000; q++)
    {
    textBox1.Text = q.ToString();
    }
    }

    你会发现当点击Start按钮后,循环会一直进行,此时窗体会出现假死的状态,如:无法拖动。直到循环结束,textBox1中才会显示出结果。如何解决窗体的假死状态??

    修改以上代码如下:

    private void btnStart_Click(object sender, EventArgs e)
    {
    for (int q = 0; q < 100000; q++)
    {
    textBox1.Text = q.ToString();
    //实时响应文本框中的值
    Application.DoEvents();
    }
    }

    此时再次点击Start按钮后,textBox中的数字会不断改变,同时,你也可以拖动窗体。。。

    但是这样使用Application.DoEvents()好吗?如果用多线程来实现相同的效果呢?

    多线程实现代码如下:

    public Form1()
    {
    InitializeComponent();
    //不捕获跨线程调用引起的异常
    CheckForIllegalCrossThreadCalls = false;
    }
    private void btnStart_Click(object sender, EventArgs e)
    {
    Thread s1 = new Thread(new ThreadStart(ThreadMeth));
    s1.Start();
    }
    public void ThreadMeth()
    {
    for (int q = 0; q < 100000; q++)
    {

    textBox1.Text = q.ToString();
    }
    }

    注意Form1()里面添加了一行代码,解决跨线程调用产生的异常。

    以上代码和使用Application.DoEvents()达到相同的效果。

    下面我们来比较一下,使用Application.DoEvents()和使用多线程哪个更耗时?

    代码如下:
    public void ThreadMeth()
    {
    label1.Text = DateTime.Now.ToString();
    for (int q = 0; q < 100000; q++)
    {
    textBox1.Text = q.ToString();
    }
    label5.Text = DateTime.Now.ToString();

    }

    private void btnStartDo_Click(object sender, EventArgs e)
    {
    label3.Text = DateTime.Now.ToString();
    for (int q = 0; q < 100000; q++)
    {
    textBox2.Text = q.ToString();
    Application.DoEvents();//实时响应文本框中的值
    }
    label6.Text = DateTime.Now.ToString();

    }

    (假设以上比较时间的代码处在正确的位置)由此可知,Application.DoEvents()消耗的时间更少,但这里并不建议使用Application.DoEvents(),因为它会引起很多未知的错误。

    补充:由于显示的定义 CheckForIllegalCrossThreadCalls = false;并不是好的方法,下面来改进一下,如下:

    int i;                                                                                                                          
            private void btnStart_Click(object sender, EventArgs e)                                                                                                                          
            {                                                                                                                          
                Thread s1 = new Thread(new ThreadStart(ThreadMeth));                                                                                                                          
                s1.Start();                                                                                                                          
            }                                                                                                                          
            private void ThreadMeth()                                                                                                                          
            {                                                                                                                          
                for ( i = 0; i < 100000; i++)                                                                                                                          
                {                                                                                                                          
                    MethodInvoker mi = new MethodInvoker(Count);                                                                                                                          
                    this.Invoke(mi);                                                                                                                          
                    //BeginInvoke(mi);                                                                                                                          
                }                                                                                                                          
            }                                                                                                                          
            private void Count()                                                                                                                          
            {                                                                                                                          
                 textBox1.Text = i.ToString();                                                                                                                          
            }

    MethodInvoker实质上是一个委托,查看其定义可知...

    using System;                                                         
                                                                                                                       
    namespace System.Windows.Forms                                                         
    {                                                         
        // 摘要:                                                         
        //     表示一个委托,该委托可执行托管代码中声明为 void 且不接受任何参数的任何方法。                                                         
        public delegate void MethodInvoker();                                                         
    }

    以上用匿名委托的方式似乎更简洁,代码如下:

    private void btnStart_Click(object sender, EventArgs e)                  
            {                  
                new Thread((ThreadStart)(delegate()                  
                    {                  
                        for (int i = 0; i < 10000; i++)                  
                        {                  
                            label1.Invoke((MethodInvoker)delegate()                  
                            {                  
                                 textBox1.Text = i.ToString();                  
                            });                  
                        };                  
                    }))                  
                    .Start();                  
            }

    在次线程上计算,在主线程上调用label。

  • 相关阅读:
    java 深克隆(深拷贝)与浅克隆(拷贝)详解
    设计模式之单例模式
    设计模式之工厂模式
    批量下载google 字体小工具
    LBPL--基于Asp.net、 quartz.net 快速开发定时服务的插件化项目
    测试
    WCF 生产json对外的接口
    四舍五入小算法 (以前写的,采用拆分)
    自己动手写控件(模仿mvc htmlhelper的类)
    步骤详解安装Apache web服务器
  • 原文地址:https://www.cnblogs.com/LiaoHao/p/3125829.html
Copyright © 2020-2023  润新知