Warum nicht die Kontrolle update/refresh-Mitte-Prozess
Ich habe eine windows-form (C#.NET) mit einem statusLabel, dass ich kann nicht scheinen, um zu aktualisieren, in der Mitte eines Prozesses, in event-handler-Methoden. Mein code sieht wie folgt aus...
void Process_Completed(object sender, EventArgs e)
{
string t = "Process is finished!";
this.Invoke(new StatusLabelUpdator(updateStatusLabel), new object[] { t });
}
void Process_Started(object sender, EventArgs e)
{
string t = "Process has begun";
this.Invoke(new StatusLabelUpdator(updateStatusLabel), new object[] { t });
}
private delegate void StatusLabelUpdator(string text);
private void updateStatusLabel(string text)
{
StatusLabel1.Text = text;
statusStrip1.Invalidate();
statusStrip1.Refresh();
statusStrip1.Update();
}
Wenn ich den code ausführen, sobald der Prozess beginnt, die Process_Started-Methode ausgelöst, und ein paar Sekunden später die Process_Completed-Methode ausgelöst. Aus irgendeinem Grund kann ich nicht bekommen, das status-label, um überhaupt angezeigt "Prozess begonnen hat". Es wird nur immer angezeigt "Vorgang beendet!". Wie Sie sehen können, habe ich versucht, ungültig, Auffrischung und Aktualisierung der status-Streifen, enthält die status-label, aber kein Erfolg. Ich kann Sie nicht anrufen-update/aktualisieren/invalidate auf dem statuslabel selbst, weil diese Methoden nicht zur Verfügung stehen. Was mache ich falsch?
ZUSÄTZLICHE INFO:
Den "Prozess" wird gestartet, indem eine Schaltfläche, klicken Sie auf die form, die dem Aufruf einer Methode in eine separate Klasse, die wie folgt aussieht:
public void DoSomeProcess()
{
TriggerProcessStarted();
System.Threading.Thread.Sleep(2000); //For testing..
TriggerProcessComplete();
}
innen die TriggerProcessxxxx Methoden, die ich auslösen der Ereignisse, die mit diesem code...
var EventListeners = EH.GetInvocationList(); //EH is the appropriate EventHandler
if (EventListeners != null)
{
for (int index = 0; index < EventListeners.Count(); index++)
{
var methodToInvoke = (EventHandler)EventListeners[index];
methodToInvoke.BeginInvoke(this, EventArgs.Empty, EndAsyncEvent, new object[] { });
}
}
Endlich, ich habe Application.DoEvents()
zu den updateStatusLabel
Methode, aber es hat nicht geholfen. Ich bin noch immer das gleiche Ergebnis. Hier ist mein update-Methode.
private void updateStatusLabel(string text)
{
StatusLabel1.Text = text;
statusStrip1.Refresh();
Application.DoEvents();
}
Also ich denke, die "Verarbeitung" statt auf den UI-thread aber-Event-Handler aufgerufen wird, auf seinen eigenen thread, dann startet das control-update wieder auf den UI-thread. Ist dies eine dumme Art und Weise, Dinge zu tun? Hinweis: Die Klasse enthält die DoSomeProcess () - Methode in eine separate .NET ClassLibrary, die ich bin Referenzierung.
InformationsquelleAutor PICyourBrain | 2010-02-26
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie Ihre Verarbeitung auf dem UI-thread werden nicht in der Lage, etwas anderes zu tun (wie Neuzeichnen aktualisiert Etiketten), während die Verarbeitung läuft. So zum Beispiel, wenn die Verarbeitung geschieht, weil der Benutzer auf eine Schaltfläche, und ist ausgelöst durch den button-Klick-Prozedur (ohne es ausdrücklich zu platzieren in einem anderen thread), läuft es auf dem UI-thread. Obwohl Sie aktualisieren den text des Labels, Sie werden nicht gezogen, bis es eine paint-Nachricht empfängt, an welcher Stelle es wahrscheinlich zu beschäftigt damit, Ihre Verarbeitung.
Die Antwort ist zu tun, lang andauernde Verarbeitung auf einem separaten thread. Der hack (IMHO), ist die Verwendung
Anwendung.DoEvents
zu lassen der UI-thread tun, einige UI-Sachen während Ihrer Bearbeitung. Wenn Sie einer von denen nach Aktualisierung der label und, bevor Sie Ihre Verarbeitung, Chancen sind ziemlich hoch, das label erhalten neu gestrichen. Aber dann, während der Verarbeitung keine weiteren paint-Ereignisse können verarbeitet (die zur Hälfte gezeichnet windows, wenn jemand bewegt einen anderen app-Fenster über Ihre app und wieder zurück, etc.). Daher mein Aufruf es ein hack (obwohl, äh, äh, ich bin dafür bekannt, es zu tun 🙂 ).Bearbeiten Update basierend auf Ihren änderungen:
Re
Gehe ich davon aus
DoSomeProcess
ausgelöst wird von dem UI-thread (z.B. in direkter Reaktion auf das klicken auf eine Schaltfläche oder ähnliches). Wenn ja, dann ja, die Verarbeitung ist definitiv auf dem UI-thread. DaTriggerProcessStarted
löst Ihre callback - asynchron überBeginInvoke
Sie haben keine Ahnung, wenn es ausgeführt wird, aber in jedem Fall Ihren code dann sofort startet in der Verarbeitung, nie nachgeben, so dass niemand sonst wird in der Lage sein zu greifen, der thread. Da das der UI-thread, der Aufruf der delegate-block auf derInvoke
rufen Sie die Einstellung der label-text, worauf es sich zu warten, für den UI-thread (was ist busy-Verarbeitung). (Und das ist vorausgesetzt, es ist geplant auf einem anderen thread, ich konnte nicht 100% überzeugen Sie mich entweder Weg, denn Microsoft hat zwei verschiedeneBeginInvoke
s -- die IIRC einer der Designer, die anerkannt hat, war eine Wirklich Dumme Idee -- und es ist schon eine Weile her, seit ich kämpfte mit diesem Zeug.)Wenn Sie die
TriggerProcessStarted
Anrufe auf Ihre Rückrufe synchron, Sie sollten in Ordnung sein. Aber im Idealfall planen Sie die Verarbeitung (wenn es die nicht tun, UI) auf einem eigenen thread statt.NACH EDIT: Du hast Recht. Ich verließ BeginInvoke allein, sondern änderte meine Schaltfläche click-Ereignis zu starten DoSomeWork auf seinen eigenen thread. Dass es behoben!
Cool, froh, dass geholfen!
InformationsquelleAutor T.J. Crowder