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)
没有 return
或 break
,操作系统无法向应用程序发送任何进一步的事件。它们被放入队列中等待发送, 但永远不会被接走。
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();
在此期间
我创建了一个 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)
没有 return
或 break
,操作系统无法向应用程序发送任何进一步的事件。它们被放入队列中等待发送, 但永远不会被接走。
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();
在此期间