2016-01-30 3 views
1

Я создал приложение Window Form Console, в котором я читаю файл, написанный другим консольным приложением. Другое консольное приложение напишет о статусе какого-либо процесса, и приложение формы окна прочитает статус и соответственно обновит текстовое поле статуса. Я написал следующий код для вышеуказанного сценария.Приложение Window Form не отвечает

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

Никогда, * никогда *, ** никогда ** не записывайте 'while (true)' петли в графическом коде. Используйте таймер. –

ответ

3

Вы должны понимать архитектуру приложения GUI.

Все взаимодействия с пользователем происходят в одном потоке.

Это включает в себя реагировать на такие вещи, как события мыши и клавиатуры и т.д.

Если один из этих событий произойдет, вы можете справиться с этим событием и сделать что-то в ответ на него.

Но пока вы не вернетесь из обработчика, приложение не сможет получать дальнейшие уведомления (сообщения Windows aka events).

Я подозреваю, что у вас есть код выше либо в конструкторе, либо в том или ином обработчике событий. Поскольку вы никогда не выйти (бесконечный цикл, из-за while(true) без return или break, операционная система не может посылать дальнейшие события в приложение. Они получают положенные в очереди отправки, но никогда не получить взяла.

для Windows обнаружит эту ситуацию и дать вам диалоговое сообщение Not Responding.

я полагаю, что, вместо того, чтобы код внутри цикла while(true), вы создаете Timer с подходящим Interval и поставить тело заявления в то время как (т.е. бит между { и }, но а не while(true)) в обработчике Tick.

1

Лучше использовать код внутри таймера. Тем не менее, вам нужно убедиться, что нет двух разных потоков одновременно с доступом к файлу. Вы должны были использовать блокировку во время чтения и записи.

0

У меня есть шаблон, который я использую для выполнения длительных задач из потока пользовательского интерфейса. Чтобы увидеть это, создайте проект 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 
     } 
    } 
} 
Смежные вопросы