2016-09-20 2 views
1

Wenn Sie in C# WinForms ein Dialogfeld öffnen, wird die Ausführung von Code nach dem Dialogfeld show nicht fortgesetzt, bis Sie auf OK klicken. So viel passiert offensichtlich. Der Haupt-Thread kann jedoch weiterhin Code ausführen, während das Dialogfeld geöffnet ist. Daher blockiert das Dialogfeld den Hauptthread nicht, aber es blockiert den spezifischen Bereich des Folgecodes.Wie verhindern Dialoge die Codeausführung, ohne den Hauptthread zu blockieren?

Ich bin gespannt, wie genau das funktioniert. Könntest/wie würdest du sowas umsetzen? (Ich möchte das nicht tun, ich habe nur festgestellt, dass ich nicht vollständig verstehe, wie die Dialogfelder funktionieren, ohne Threadausführung zu blockieren.)

Betrachten Sie diesen Beispielcode und Projekt mit zwei Schaltflächen und einem Etikett. Das Label zeigt den Wert eines Zählers an. Ein Timer erhöht den Zähler alle 500 Millisekunden. Eine der Schaltflächen öffnet einen Dialog. Der andere führt eine Schleife aus, die Thread.Sleep zehnmal für eine Sekunde aufruft. Sie werden feststellen, dass der Label Counter bei geöffnetem Dialogfeld inkrementiert wird, während thread.sleep die Ausführung aller Timer bis zum Ende blockiert.

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Threading; 

namespace MainThreadPauser 
{ 
    public partial class Form1 : Form 
    { 
     int counter = 0; 
     public Form1() 
     { 
      InitializeComponent(); 
      System.Windows.Forms.Timer t = new System.Windows.Forms.Timer(); 
      t.Interval = 500; 
      t.Enabled = true; 
      t.Tick += new EventHandler(t_Tick); 
      t.Start(); 
     } 

     void t_Tick(object sender, EventArgs e) 
     { 
      BeginInvoke((Action)(() => { 
       AddToCounter(); 
      })); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      MyDialog dlg = new MyDialog(); 
      dlg.ShowDialog(this); 

      AddToCounter(5000); 
     } 

     private void AddToCounter(int value = 1) 
     { 
      counter += value; 
      label1.Text = counter.ToString(); 
     } 

     private void button2_Click(object sender, EventArgs e) 
     { 
      for (int x = 0; x < 10; x++) 
      { 
       Thread.Sleep(1000); 
      } 
     } 
    } 
} 
+0

UI-Aktivität wird im Kontext von Nachrichten ausgeführt, die im Hauptthread gesendet (oder gesendet) werden. – bvj

Antwort

2

Kurz:

Ihr GUI-Thread läuft ein messagepump, es behandelt Klick/Bewegung/Schlüssel etc Nachrichten.

Wenn Sie einen modalen Dialog geöffnet, läuft der Nachrichtendialog eine ‚neue‘ messagepump/Schleife innerhalb des Dialogs (while-Schleife), so dass alle Fenster Nachrichten behandelt werden, aber es wird die aktuelle Methode blockieren, wo die Show Der Dialog wird aufgerufen, bis Sie den Dialog schließen. Das ist, warum Timer (sie arbeiten auf Windowmessages) und das Fenster neu zu streichen arbeitet noch. Der Dialog deaktiviert Ihr Fenster, so dass Sie das Dialogfeld nicht passieren können.

+0

Ich wusste von dem Nachrichtensystem, ich dachte einfach nicht, dass der Dialog das tun würde. Also frage ich mich dann ob es möglich ist meinen eigenen Nachrichtenpumpen Simulator zu schreiben. Nicht, dass ich in einem echten Programm nur für Wissenschaft/Lernen möchte. – teynon

+1

Sicher, es ist ** nicht ** ratsam, aber eine 'while (true) Application.DoEvents();' wird tun. Natürlich gibt es bessere Wege, aber das ist einfach. Sie könnten nach 'Windows.Forms' und' MessagePump' oder 'MessageLoop' suchen. Damals (Visual C++ 6.0) mussten wir sie selbst schreiben. TranslateMessage/DispatchMessage usw._ –

Verwandte Themen