窗口表单应用程序没有响应

时间:2016-01-30 09:46:08

标签: c# forms window

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

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

当我运行窗口表单应用程序时,它显示表单无响应,但是当我将注释掉这些代码时,它将顺利运行,但对我来说,重要的是更新状态。

3 个答案:

答案 0 :(得分:3)

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

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

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

如果其中一个事件发生,您可以处理该事件并做出回应。

但是,在您从处理程序返回之前,应用程序将无法再接收任何通知(Windows Messages aka事件)。

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

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

我建议,不要在while(true)循环中包含代码,而是使用合适的Timer创建Interval,然后设置正文 tick语句中的while语句(即{}之间的位,而不是while(true)本身)。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

我有一个模式,用于从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
        }
    }
}