Application.DoEvents() 在应用程序运行时不断调用?

Posted

技术标签:

【中文标题】Application.DoEvents() 在应用程序运行时不断调用?【英文标题】:Application.DoEvents() called constantly while application is running? 【发布时间】:2011-07-14 11:14:52 【问题描述】:

我试图为我的应用程序添加一个表单兑现模块,我实现了这个 msdn 示例:Form Stacking and Caching

对于那些无法下载示例的人,这是包含我所指代码的类:

using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Threading;

namespace GUIFramework 
    public class FormStack : CollectionBase 
        private System.Collections.ArrayList stack = new ArrayList();

    public void Run() 
        do 
            System.Windows.Forms.Application.DoEvents();
         while(List.Count > 0);
    

    public void Stop() 
        // nicely destroy each Form
        foreach(StackForm sf in List) 
            sf.Dispose();
        
        // clear the list to kill the message pump in Run()
        List.Clear();
    

    public void Push(Type FormType) 
        // only allow 1 Push at a time to maintain cache and stack itegrity
        Monitor.Enter(this);

        foreach(StackForm sf in List) 
            if(sf.GetType().Name.Equals(FormType.Name)) 
                // form is cached so display cached version
                sf.Visible = true;

                // add it to the stack
                stack.Add(FormType.Name);

                return;
            
        

        // the Form wasn't cached, so create it
        StackForm form = Preload(FormType);

        // display it
        form.Visible = true;

        // add a close event handler
        form.FormClosed += new FormClose(form_FormClosed);

        // add it to the stack
        stack.Add(FormType.Name);

        Monitor.Exit(this);
    

    public StackForm Preload(Type FormType) 
        StackForm form = (StackForm)Activator.CreateInstance(FormType);

        // get data on a separate thread
        form.LoadData();

        // build the form
        form.InitializeComponent();

        // wait for the data thread to finish
        form.threadRunning.WaitOne();

        // now populate the controls with any retrieved data
        form.Populate();

        form.MinimizeBox = false;  // required to get close event on PPC!

        // add it to the cache
        List.Add(form);

        return form;
    

    public void Pop(uint FormsToPop) 
        if(stack.Count <= FormsToPop) 
            throw new Exception("You cannot Pop the entire stack!");
        
        else 
            // remove from stack but not cache
            for(int i = 0 ; i < FormsToPop ; i++) 
                stack.RemoveAt(stack.Count - 1);
            

            foreach(StackForm sf in List) 
                // find the last form in the stack
                if(sf.GetType().Name.Equals(stack[stack.Count - 1])) 
                    // make it visible
                    sf.Visible = true;
                
            
        
    

    private void form_FormClosed() 
        Pop(1);
    

    public override string ToString() 
        string message = "There are " + List.Count.ToString() + " forms cached\r\n";
        message += "Stack contents:";

        for(int i = stack.Count - 1 ; i >= 0 ; i--) 
            message += "\r\n" + stack[i].ToString();
        

        return message;
    


Run() 方法在应用程序运行时不断调用Application.DoEvents()。我很难相信这对应用程序来说是一件好事。我很想听听对此的其他意见。谢谢。

【问题讨论】:

【参考方案1】:

首先,您需要了解 WinForms 应用程序的一般工作原理。 Application.Run 调用的深处是一段代码,通常称为消息泵。这是一个调用 GetMessage、TranslateMessage 和 DispatchMessage 的无限循环。本质上,Application.DoEvents 调用该循环的一次循环。您正在查看的 DoEvents 循环只是执行此操作。

现在为什么,确切地说,甚至需要那个电话,我不能老实说。这很糟糕,因为我编写了代码,但在我的辩护中,这段代码已经有将近十年的历史了,我几乎不记得我上周做了什么。

如果删除循环,会发生什么?我没有看到任何表明您会得到绘图工件或绘图失败(这是添加调用的典型原因)的任何内容,但此代码也是针对 CF 1.0 编写的,因此很可能是为了克服运行时限制。

对于它的价值,我 revisited and rewrote the code in 2009 并且重写没有循环(甚至没有 Run 方法)。

顺便说一句,我看到 Push 中有一个错误。 foreach 循环有一个return 而没有执行 Monitor.Exit。我可能会重写该方法以使用 lockfinally 块来调用 Monitor.Exit。

【讨论】:

以上是关于Application.DoEvents() 在应用程序运行时不断调用?的主要内容,如果未能解决你的问题,请参考以下文章

什么相当于 WPF 应用程序中的 Application.DoEvents()

WPF 中的 Application.DoEvents() 在哪里?

Application.DoEvents() 在应用程序运行时不断调用?

与 Application.DoEvents() 和 PictureBox 混淆 [重复]

等待 WebBrowser 完成加载时 Application.DoEvents() 出现问题

Application.DoEvents()的使用