Formular reagiert nicht, wenn eine andere Operation in C # ausgeführt wird

8

Ich habe ein Formular (Entwickelt in C # mit VS2010) mit einer Fortschrittsleiste. Es ist eine Art Stoppuhrform, in der ich den Fortschrittsbalken in etwa 10 Sekunden befülle .... Wenn die Zeit abläuft, füllt sich der Fortschrittsbalken entsprechend .... Bedeutet nach 5 Sekunden, wird Fortschrittsbalken zu 50% gefüllt und so weiter ....

Ich habe eine for-Schleife verwendet, um diese Operation durchzuführen: -

%Vor%

Ich habe Thread.Sleep von 50 ms verwendet, damit der Fortschrittsbalken reibungslos aktualisiert wird. Für 1 Sek. Wird schrittweise erhöht.

Problem ist, wenn ich irgendeine andere Operation wie das Verschieben dieses Formulars oder sogar das Klicken auf ein anderes Symbol auf Desktops mache, dieses Formular "nicht reagiert" .... Aber es führt den Vorgang aus und nach 10 Sekunden, es wieder seinen Zustand und zeigt das Popup an, das anzeigt, dass 10 Sekunden mit Progress Bar Full abgelaufen sind.

Vielen Dank für Ihre Hilfe und Entschuldigung für die Verwendung dieser komplizierten Sprache.

Grüße, Swanand

Update : Ich habe dieses Problem mit Hilfe von Answers gelöst. Ein häufiger Fehler, den ich kennengelernt habe, ist das Vergessen von " Applications.DoEvents() " zusammen mit " update() " ... Wenn Sie diese Zeile eingeben, gibt es weniger Chancen, "gehängt" zu werden!

    
Swanand 07.02.2011, 07:51
quelle

5 Antworten

13

Sie führen einen lang andauernden Vorgang im Benutzeroberflächenthread aus, was bedeutet, dass die "Nachrichtenschleife" der Benutzeroberfläche (die für die Behandlung von Ereignissen wie Benutzereingaben und die Aktualisierung des Bildschirms zuständig ist) keine Chance zum Ausführen hat.

Sie sollten die lang andauernde Operation für einen anderen Thread ausführen (unabhängig davon, ob Sie selbst oder einen Hintergrundthread erstellen) und entweder BackgroundWorker , um Ihre Fortschrittsanzeige einfach zu aktualisieren, oder verwenden Sie Control.Invoke/BeginInvoke , um einen Delegat-Aufruf an den UI-Thread zurückzumelden, wenn Sie die Benutzeroberfläche aktualisieren müssen. (Sie müssen die Steuerelemente nicht vom falschen Thread aktualisieren.)

Wenn Ihre einzige UI-Interaktion einen Fortschrittsbalken ausfüllt, empfehle ich die Verwendung von BackgroundWorker .

Wenn du nicht wirklich "echte" Arbeit machst, sondern nur darauf wartest, dass die Zeit vergeht, kannst du stattdessen System.Windows.Forms.Timer verwenden. Dies wird im UI-Thread "aktiviert", blockiert jedoch nicht den UI-Thread zwischen Ticks. Sie sollten dies nur verwenden, wenn Sie nicht viel zu tun haben - wenn es wirklich nur eine Fortschrittsleiste aktualisiert, nicht etwa eine Datei verarbeitet usw. Beachten Sie, dass Sie nicht "arbeiten" sollten. Verlass dich darauf, dass der Timer genau "pünktlich" abfeuert - du solltest die Position des Fortschrittsbalkens wahrscheinlich anhand der beobachteten Zeit und nicht anhand der beobachteten Anzahl von Ticks setzen.

    
Jon Skeet 07.02.2011, 07:53
quelle
7

Sie blockieren den UI-Thread, dh er verarbeitet keine Ereignisse wie "Farbe". Um dies richtig durchzuführen, sollten Sie etwas wie BackgroundWorker verwenden und nur die Benutzeroberfläche vom Fortschrittsereignis aktualisieren.

%Vor%     
Marc Gravell 07.02.2011 07:53
quelle
2

Sie blockieren den Haupt-UI-Thread. Sie können dazu einen Hintergrundarbeiter verwenden. Weitere Informationen finden Sie in MSDN

    
Anuraj 07.02.2011 07:53
quelle
0

Die von Marc vorgeschlagene Antwort wird Ihnen helfen. Lon laufende Operationen können dazu führen, dass Ihre Anwendung abstürzt oder nicht reagiert. Ich habe einen Blogpost, der sich auf die Verwendung der Hintergrundarbeiterklasse bezieht.

Ссылка

    
Prashant 07.02.2011 08:02
quelle
0

Wenn Sie Ihren Code ausführen möchten, sollten Sie diesen Code in eine Funktion einfügen und diese Funktion mit einem Thread aufrufen.

%Vor%

b'caz Thread.sleep (100) stoppt den gesamten Kontext, den Sie nicht möchten.

    
Vishal Patwardhan 07.02.2011 11:50
quelle

Tags und Links