繁体   English   中英

Windows 窗体应用程序没有响应

[英]Windows Forms Application is not responding

我创建了一个 Windows 窗体控制台应用程序,我正在其中读取由另一个控制台应用程序编写的文件。 另一个控制台应用程序将写入某个进程的状态,Windows 窗体应用程序将读取状态并相应地更新状态文本框。 我为上述场景编写了以下代码。

while (true)
{
    if ((new FileInfo(filename)).Length > 0)
    {
         Status = File.ReadAllText(filename, Encoding.ASCII);
         System.IO.File.WriteAllText(filename, string.Empty);

         Statustb.Text = Status;
         Statustb.Refresh();
                    
         if (Status.Equals("Data Got Loaded"))
         {
             Environment.Exit(0);
         }
     }
 }

当我运行 Windows Forms 应用程序时,它显示“Form Not Responding”,但是当我注释掉这些行时,它会顺利运行。 但对我来说,更新状态很重要。

您必须了解 GUI 应用程序的体系结构。

与用户的所有交互都发生在一个线程上。

这包括对鼠标和键盘事件等做出反应。

如果这些事件之一发生,您可以处理该事件并对其进行响应。

但是,在您从处理程序返回之前,应用程序将无法接收任何进一步的通知(Windows 消息又名事件)。

我怀疑您在构造函数或一个或其他事件处理程序中具有上述代码。 由于您永远不会退出(无限循环,由于while(true)没有returnbreak ,操作系统无法向应用程序发送任何进一步的事件。它们被放入要发送的队列中,但永远不会被拾取。

Windows 将检测到这种情况并为您提供“ Not Responding对话框消息。

我建议,不要将代码放在while(true)循环中,而是创建一个具有合适IntervalTimer ,并放置 while 语句的主体(即{}之间的位,而不是while(true)本身 ) 在 Tick 处理程序中。

最好在计时器内使用代码。 不过,您需要确保没有两个不同的线程同时访问一个文件。 你应该在读写它时使用过锁。

我有一个模式,用于从 UI 线程中获取长时间运行的任务。 要查看它,请创建一个 Winforms 项目并打开 Form1.cs 的代码隐藏。 删除内容并将以下内容复制到该文件中。 它应该运行并且它有描述它正在做什么的注释。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace POC_DoEvents_alternate
{
    public partial class Form1 : Form
    {
        private Button button1;
        private Button button2;
        private TextBox textbox1;

        public Form1()
        {
            InitializeComponent();

            // programmatically create the controls so that the
            // entire source code is contained in this file.
            // normally you wouldn't do this.

            button1 = new Button();
            button1.Name = "button1";
            button1.Enabled = true;
            button1.Location = new Point(12, 12);
            button1.Size = new Size(144, 35);
            button1.Text = "button1";
            button1.Click += button1_Click;
            this.Controls.Add(button1);

            button2 = new Button();
            button2.Name = "button2";
            button2.Enabled = false;
            button2.Location = new Point(12, 53);
            button2.Size = new Size(144, 35);
            button2.Text = "button2";
            button2.Click += button2_Click;
            this.Controls.Add(button2);

            textbox1 = new TextBox();
            textbox1.Name = "textbox1";
            textbox1.Location = new Point(12, 94);
            textbox1.ReadOnly = true;
            textbox1.Size = new Size(258, 22);
            this.Controls.Add(textbox1);

            this.Load += new System.EventHandler(this.Form1_Load);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            textbox1.Text = "You can't press button 2 yet...";
            button1.Enabled = true;
            button2.Enabled = false;
            this.Cursor = Cursors.AppStarting;

            // start the long running task in a separate background thread
            ThreadPool.QueueUserWorkItem(Async_LongRunningTask, "Form1_Load");

            // calling the QueueUserWorkItem will not block. Execution will
            // contiune immediately with the lines below it.

            textbox1.BackColor = Color.LightPink;

            // this event handler finishes quickly so the form will paint and
            // be responsive to the user.
        }

        private void button1_Click(object sender, EventArgs e)
        {
            textbox1.Text = "Button 1 pressed";
        }

        private void button2_Click(object sender, EventArgs e)
        {
            textbox1.Text = "Button 2 pressed";
        }

        private void Async_LongRunningTask(object state)
        {
            // put all your long running code here, just don't put any
            // UI work on this thread

            Thread.Sleep(5000);     // simulates a long running task

            // put any UI control work back on the UI thread
            this.Invoke((MethodInvoker)delegate
            {
                button2.Enabled = true;
                textbox1.Text = "End of long running task: " + state.ToString();
                textbox1.BackColor = SystemColors.Control;
                this.Cursor = Cursors.Default;

                // as with anything on the UI thread, this delegate
                // should end quickly
            });

            // once the delegate is submitted to the UI thread
            // this thread can still do more work, but being a
            // background thread, it will stop when the application
            // stops.

            Thread.Sleep(2000);     // simulates a long running task
        }
    }
}

你可以加
using System.Windows.Forms;
Application.DoEvents();
在While

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM