Compact Framework/Threading - MessageBox zeigt über andere Steuerelemente nach option gewählt wird

StackOverflow https://stackoverflow.com/questions/10071

Frage

Ich arbeite an einer app, die packt und installiert eine Reihe von updates aus einem externen server, und brauchen etwas Hilfe mit threading.Der Benutzer diesem Prozess folgt:

  • Klickt auf die Schaltfläche
  • Die Methode prüft, ob updates, count zurückgegeben wird.
  • Wenn größer als 0, dann bitten Sie den Benutzer, wenn Sie wollen zu installieren, mit der MessageBox.Show().
  • Wenn ja, läuft es durch eine Schleife und Aufruf von BeginInvoke() auf die run () - Methode jedes update, um es im hintergrund auszuführen.
  • Mein update-Klasse verfügt über einige Ereignisse, die zu einer Aktualisierung ein Fortschrittsbalken etc.

Die progress bar updates sind in Ordnung, aber die MessageBox ist nicht vollständig aus der Anzeige gelöscht, weil die update-Schleife beginnt direkt nach der der Benutzer auf ja klickt (siehe screenshot unten).

  • Was soll ich tun, um die messagebox augenblicklich verschwinden, bevor die update-Schleife beginnt?
  • Sollte ich die Verwendung von Threads statt BeginInvoke()?
  • Sollte ich das tun, werden die ersten Updates auf einem separaten thread und aufrufen der MessageBox.Karte() aus diesem thread?

Code

// Button clicked event handler code...
DialogResult dlgRes = MessageBox.Show(
    string.Format("There are {0} updates available.\n\nInstall these now?", 
    um2.Updates.Count), "Updates Available", 
    MessageBoxButtons.YesNo, 
    MessageBoxIcon.Question, 
    MessageBoxDefaultButton.Button2
);

if (dlgRes == DialogResult.Yes)
{
    ProcessAllUpdates(um2); 
}

// Processes a bunch of items in a loop
private void ProcessAllUpdates(UpdateManager2 um2)
{
    for (int i = 0; i < um2.Updates.Count; i++)
    {
        Update2 update = um2.Updates[i];

        ProcessSingleUpdate(update);

        int percentComplete = Utilities.CalculatePercentCompleted(i, um2.Updates.Count);

        UpdateOverallProgress(percentComplete);
    }
}

// Process a single update with IAsyncResult
private void ProcessSingleUpdate(Update2 update)
{
    update.Action.OnStart += Action_OnStart;
    update.Action.OnProgress += Action_OnProgress;
    update.Action.OnCompletion += Action_OnCompletion;

    //synchronous
    //update.Action.Run();

    // async
    IAsyncResult ar = this.BeginInvoke((MethodInvoker)delegate() { update.Action.Run(); });
}

Screenshot

Windows Mobile Bug

War es hilfreich?

Lösung

Ihre Benutzeroberfläche nicht aktualisiert wird, weil die ganze Arbeit geschieht in der Benutzeroberfläche thread.Ihr Anruf an:

this.BeginInvoke((MethodInvoker)delegate() {update.Action.Run(); }) 

sagt aufrufen-update.Aktion.Run() auf dem thread, der erzeugt "diese" (Ihre form), ist das user-interface thread.

Application.DoEvents()

wird in der Tat geben der UI-thread die chance, um den Bildschirm neu zeichnen, aber ich würde geneigt sein, neues zu schaffen delegieren, und der Aufruf von BeginInvoke auf, dass.

Dies wird das update auszuführen.Aktion.Die Run () - Funktion in einem separaten thread zugeordnet, die in der thread-pool.Sie können dann kontrollieren Sie das IAsyncResult-bis die Aktualisierung abgeschlossen ist, wird die Abfrage des update-Objekts für seine Fortschritte nach jedem check (weil Sie nicht haben kann, den anderen thread zu aktualisieren die Fortschritt bar/UI), dann aufrufende Anwendung.DoEvents().

Sie sind auch nennen soll EndInvoke() danach sonst können Sie am Ende leckt Ressourcen

Ich würde auch versucht werden, um eine cancel-Taste auf der Status-dialog, und fügen Sie ein timeout, andernfalls, wenn das update feststeckt (oder dauert zu lange), dann Ihre Anwendung wird gesperrt für immer.

Andere Tipps

Haben Sie versucht, indem Sie eine

Application.DoEvents()

hier

if (dlgRes == DialogResult.Yes)
{
   Application.DoEvents(); 
   ProcessAllUpdates(um2); 
}

@ John-Unglaublich

Sie können sich mit nicht Aufruf von EndInvoke beim Umgang mit WinForms, ohne negative Folgen.

Die einzige dokumentierte Ausnahme von der Regel, dass ich bewusst bin, ist in Windows Forms, wo du bist offiziell erlaubt zu nennen Control.BeginInvoke ohne sich die Mühe zu nennen Control.EndInvoke.

Aber in allen anderen Fällen ist beim Umgang mit der Begin/End-Async-Muster, die Sie sollten davon ausgehen, dass es undicht wird, wie Sie erklärte.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top