【问题标题】:Windows Forms Application is not respondingWindows 窗体应用程序没有响应
【发布时间】:2016-05-08 02:47:32
【问题描述】:

我创建了一个 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”,但是当我注释掉这些行时,它会顺利运行。但对我来说,更新状态很重要。

【问题讨论】:

  • 从不,nevernever 在 GUI 代码中编写 while(true) 循环。使用计时器。

标签: c# forms winforms window


【解决方案1】:

您必须了解 GUI 应用程序的架构。

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

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

如果发生这些事件之一,您可以处理该事件并做一些事情来响应它。

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

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      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
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        您可以添加
        using System.Windows.Forms;
        Application.DoEvents();
        在同时

        【讨论】:

        • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多