zoukankan      html  css  js  c++  java
  • 防止程序假死,Application.DoEvents()学习(资料收集、转载)

    Application.DoEvents的应用

    当我们在事件里面进行大量的循环操作时,windows将等待循环结束。此时界面是得不到响应的。为了在WinForm界面上实时地显示每次循环得到的结果,可以用.net提供的Application.DoEvents();
    我们定义一个TextBox(ID为txtMessage),一个Button(ID为txtTest)
    private void btnTest_Click(object sender, EventArgs e)
     {
                for (int i = 0; i < 10000; i++)
                {
                    this.txtMessage.Text = i.ToString();
                }
    }
    以上代码的运行结果:消息框内只显示9999,并且有较长的等待时间;

    为了实时显示1--9999,我们做了如下处理
    private void btnTest_Click(object sender, EventArgs e)
     {
                for (int i = 0; i < 10000; i++)
                {
                    this.txtMessage.Text = i.ToString();
                    Application.DoEvents();//实时响应对消息框的处理
                }
    }
     
    转载自:http://tmsoft.lsxy.com/index.php?id=254&load=read
     
    Application.DoEvents Method(来自MSDN)

    Processes all Windows messages currently in the message queue.

    [Visual Basic]
    Public Shared Sub DoEvents()
    [C#]
    public static void DoEvents();
    [C++]
    public: static void DoEvents();
    [JScript]
    public static function DoEvents();

    Remarks

    When you run a Windows Form, it creates the new form, which then waits for events to handle. Each time the form handles an event, it processes all the code associated with that event. All other events wait in the queue. While your code handles the event, your application does not respond. For example, the window does not repaint if another window is dragged on top.

    If you call DoEvents in your code, your application can handle the other events. For example, if you have a form that adds data to a ListBox and add DoEvents to your code, your form repaints when another window is dragged over it. If you remove DoEvents from your code, your form will not repaint until the click event handler of the button is finished executing.

    Typically, you use this method in a loop to process messages.

    CAUTION   Calling this method can cause code to be re-entered if a message raises an event.

    Example

    [Visual Basic, C#] The following code example demonstrates handling the FileOk Event and using the Application.DoEvents method. When the example runs, a user can select graphics files from an OpenFileDialog object. The selected files are displayed in the form. The DoEvents method forces a repaint of the form for each graphics file opened.To run this example paste the following code in a form containing a PictureBox named PictureBox1, an OpenFileDialog named OpenFileDialog1, and a button named fileButton. Call the InitializePictureBox and InitializeOpenFileDialog methods from the form's constructor or Load method. The example also assumes that the Click event of the Button control and the FileOK event of the OpenFileDialog are connected to the event handling methods defined in the example. When the example is running, display the dialog by clicking the button.
    [C#]
    private void InitializePictureBox()
    {
        this.PictureBox1 = new System.Windows.Forms.PictureBox();
        this.PictureBox1.BorderStyle =
            System.Windows.Forms.BorderStyle.FixedSingle;
        this.PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
        this.PictureBox1.Location = new System.Drawing.Point(72, 112);
        this.PictureBox1.Name = "PictureBox1";
        this.PictureBox1.Size = new System.Drawing.Size(160, 136);
        this.PictureBox1.TabIndex = 6;
        this.PictureBox1.TabStop = false;
    }

    private void InitializeOpenFileDialog()
    {
        this.OpenFileDialog1 = new System.Windows.Forms.OpenFileDialog();

        // Set the file dialog to filter for graphics files.
        this.OpenFileDialog1.Filter =
            "Images (*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|" +
            "All files (*.*)|*.*";

        // Allow the user to select multiple images.
        this.OpenFileDialog1.Multiselect = true;
        this.OpenFileDialog1.Title = "My Image Browser";
       
    }

    private void fileButton_Click(System.Object sender, System.EventArgs e)
    {
        OpenFileDialog1.ShowDialog();
    }


    // This method handles the FileOK event.  It opens each file
    // selected and loads the image from a stream into PictureBox1.
    private void OpenFileDialog1_FileOk(object sender,
        System.ComponentModel.CancelEventArgs e)
    {

        this.Activate();
         string[] files = OpenFileDialog1.FileNames;

        // Open each file and display the image in PictureBox1.
        // Call Application.DoEvents to force a repaint after each
        // file is read.       
        foreach (string file in files )
        {
            System.IO.FileInfo fileInfo = new System.IO.FileInfo(file);
            System.IO.FileStream fileStream = fileInfo.OpenRead();
            PictureBox1.Image = System.Drawing.Image.FromStream(fileStream);
            Application.DoEvents();
            fileStream.Close();

            // Call Sleep so the picture is briefly displayed,
            //which will create a slide-show effect.
            System.Threading.Thread.Sleep(2000);
        }
        PictureBox1.Image = null;
    }

    From:http://msdn.microsoft.com/zh-cn/library/system.windows.forms.application.doevents(en-us,VS.71).aspx

    记得第一次使用Application.DoEvents()是为了在加载大量数据时能够有一个数据加载的提示,不至于系统出现假死的现象,当时也没有深入的去研究他的原理是怎样的,结果在很多地方都用上了Application.DoEvents(),今天看到了关于这方面的一些文章,知道我以前有些用法是不当的,有些地方需要慎用Application.DoEvents()。
    首先我们先看看在循环比较大的程序中,它的作用还是不错的,起到了一个实时响应的效果,例如:

    for (int q = 0; q < 1000000; q++)
                
    {
                    textBox1.Text 
    = q.ToString();
                    Application.DoEvents();//实时响应文本框中的值
                }

    如果没有加上 DoEvents的话,由于循环时间会比较久就会出现假死的状态,而且程序不能处理其他的事件。而如果加上DoEvents的话就会对文本框的值实时响应,给用户带来较好的用户体验,可是DoEvents也带来了效率上的问题,处理同样的一个事件调用了DoEvents后效率降低了好几倍,这也是为什么要慎用的原因了。下面是我做的一个测试:

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

                label2.Text 
    = expendTime.ComputerTime();//计算耗时
            }


            
    private void button2_Click(object sender, EventArgs e)
            
    {
                expendTime.start();
                
    for (int q = 0; q < 100000; q++)
                
    {
                    textBox2.Text 
    = q.ToString();
                }

                label3.Text 
    = expendTime.ComputerTime();//计算耗时
            }


    执行耗时对比:
    从较大数据的循环中可以看出效率是很低的,所以如果能不调用DoEvents就尽量不用。也可以通过别的方法来处理的,例如多线程异步调用等。
    MSDN中的定义:
    当运行   Windows   窗体时,它将创建新窗体,然后该窗体等待处理事件。该窗体在每次处理事件时,均将处理与该事件关联的所有代码。所有其他事件在队列中等待。在代码处理事件时,应用程序并不响应。例如,当将另一窗口拖到该窗口前面时,该窗口不重新绘制。如果在代码中调用   DoEvents,则您的应用程序可以处理其他事件。例如,如果您有向   ListBox   添加数据的窗体,并将   DoEvents   添加到代码中,那么当将另一窗口拖到您的窗体上时,该窗体将重新绘制。如果从代码中移除   DoEvents,那么在按钮的单击事件处理程序执行结束以前,您的窗体不会重新绘制。   
     通常,您在循环中使用该方法来处理消息。
    转载:http://www.cnblogs.com/datong/archive/2008/04/06/1139216.html

    另外一篇英文:

    Keeping your UI Responsive and the Dangers of Application.DoEvents

    http://blogs.msdn.com/jfoscoding/archive/2005/08/06/448560.aspx

  • 相关阅读:
    VBScript学习笔记
    C#调用C++库知识点
    .Net面试经验,从北京到杭州
    杭州.Net 相关大公司,希望对大家有帮助
    一起学习《C#高级编程》3--运算符重载
    一起学习《C#高级编程》2--比较对象的相等性
    一起学习《C#高级编程》1--类型的安全性
    博客园的第一天
    基于SpringCloud+Kubernetes 微服务的容器化持续交付实战
    第一节:Docker学习 — 安装
  • 原文地址:https://www.cnblogs.com/wuhenke/p/1622614.html
Copyright © 2011-2022 走看看