2016-05-24 19 views
-1
rendert

ÄhnlichWindows Forms: Windows-Label nicht

MessageBox.Show("Test", "Test") 

ich einen ProgressWindow gemacht haben, die vor langer Lauf Aktion gezeigt wird, und versteckt danach:

ProgressWindow.Show("Test","Test") 
Thread.Sleep(20000); 
ProgressWindow.Hide(); 

die Verwendung von folgender Code:

class ProgressWindow : Form 
{ 
    private Label label1; 

    private static ProgressWindow window; 

    internal static void Show(string Message, string Caption) 
    { 
     window = new ProgressWindow(Message, Caption); 
     window.Show(); 
    } 

    internal new static void Hide() 
    { 
     (ProgressWindow.window as Control).Hide(); 
    } 

    private ProgressWindow(string Message, string Caption) 
    { 
     InitializeComponent(Message, Caption); 
    } 

    private void InitializeComponent(string Message, string Caption) 
    { 
     this.label1 = new System.Windows.Forms.Label(); 
     this.SuspendLayout(); 
     // 
     // label1 
     // 
     this.label1.Location = new System.Drawing.Point(50, 40); 
     this.label1.Name = "label1"; 
     this.label1.Size = new System.Drawing.Size(300, 120); 
     this.label1.TabIndex = 0; 
     this.label1.Text = Message; 
     // 
     // ProgressWindow 
     // 
     this.ClientSize = new System.Drawing.Size(400, 200); 
     this.ShowIcon = false; 
     this.MinimizeBox = false; 
     this.MaximizeBox = false; 
     this.ControlBox = false; 
     this.FormBorderStyle = FormBorderStyle.FixedDialog; 
     this.StartPosition = FormStartPosition.CenterScreen; 
     this.Controls.Add(this.label1); 
     this.Name = "ProgressWindow"; 
     this.Text = Caption; 
     this.TopMost = true; 
     this.ResumeLayout(false); 

    } 
} 

Das Problem ist jetzt, dass meine Statusfenster angezeigt wird, sondern in der Position des Etiketts, ther e ist nur eine weiße Box und kein Text. Außerdem, wenn ich versuche, auf das Fenster zu klicken, ändert sich der Titel von "Test" zu "Test (reagiert nicht ...)".

Warum ist das, und wie würde ich das ändern?

ich ein Problem mit dem Faden Blockierung vermutet (aber warum? Sollte nicht das Etikett gemacht werden?) Und versuchten

internal static void Show(string Message, string Caption) 
{ 
    window = new ProgressWindow(Message, Caption); 
    new Thread(t => { 
     window.Show(); 
    }).Start(); 
} 

aber die ProgressWindow Form überhaupt nicht angezeigt.

+2

Ich rate, weil Ihr lang andauernder Prozess auf dem UI-Thread ausgeführt wird. – BugFinder

+0

Das liegt daran, dass dein 'Thread.Sleep (..)' den aktuellen Thread blockiert. Der Thread ist auch für die Aktualisierung der Benutzeroberfläche zuständig. Sie sollten die Arbeitselemente in einen separaten Thread verschieben, anstatt das Fortschrittsfenster in einem anderen Thread anzuzeigen. –

+0

Das ist eine Multidupe, aber ich wüsste nicht, welche man als Dupe schließen soll. Sie müssen verstehen, dass der UI-Thread frei sein muss, um die Benutzeroberfläche zu aktualisieren, und wenn Sie * den UI-Thread * blockieren, indem Sie beispielsweise den Bugger ausschalten, kann er seine Aufgabe nicht erfüllen. Das Thema Multithreading in einer Windows-Anwendung ist überall auf dem blutigen Platz abgedeckt. Ich schlage vor, dass Sie Ihre Suchanfragen auf das vergangene Jahr beschränken, sodass Sie keines der älteren Muster verwenden, z. B. einen BackgroundWorker verwenden. – Will

Antwort

0

Ja, das Problem liegt an Thread-Blockierung. Wenn Thread.Sleep() aufgerufen wird, tut der aktuelle Thread nichts, was bedeutet, dass keine Windows-Nachrichten verarbeitet werden. Dies verhindert, dass Ihr Fortschrittsdialog seine Benutzeroberfläche vollständig anzeigt.

Ich bin mir nicht genau sicher, warum die Methode Show() auf einem Hintergrundthread nicht funktioniert, aber ich glaube, dass WinForms erfordert, dass der UI-Thread ein Single Threaded Apartment ist und standardmäßig Threads Multi-Threaded Apartment sind.

Um dies richtig zu implementieren, würde ich vorschlagen, die BackgroundWorker Klasse zu verwenden. Es erstellt automatisch einen Hintergrundthread, um die lang andauernde Arbeit auszuführen, und löst ein Ereignis aus, sobald die Arbeit abgeschlossen ist. Sie können es so etwas wie folgt verwenden:

ProgressWindow.Show("Test","Test"); 

var worker = new BackgroundWorker(); 
worker.DoWork += (sender, args) => { 
    // perform your long running task here, this is a background thread 
    Thread.Sleep(2000); 
}; 
worker.RunWorkerCompleted += (sender, args) => { 
    // update the UI here, this is running on the UI thread 
    ProgressWindow.Hide(); 
} 
worker.RunWorkerAsync(); 

Beachten Sie, dass RunWorkerAsync() sofort zurückkehren, so die Benutzeroberfläche, die Tatsache umgehen müssen, dass der Benutzer mit der Benutzeroberfläche interagieren kann, bevor die Hintergrundaufgabe beendet ist.