[英]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)
没有return
或break
,操作系统无法向应用程序发送任何进一步的事件。它们被放入要发送的队列中,但永远不会被拾取。
Windows 将检测到这种情况并为您提供“ Not Responding
对话框消息。
我建议,不要将代码放在while(true)
循环中,而是创建一个具有合适Interval
的Timer
,并放置 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.