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 应用程序的体系结构。

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

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

如果这些事件之一发生,您可以处理该事件并采取相应措施。

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

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

Windows 将检测到这种情况并给你 Not Responding 对话框消息。

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

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

我有一个模式,用于从 UI 线程中获取较长的 运行ning 任务。要查看它,请创建一个 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();
在此期间