2 Stimmen

Warum wird Dispatcher.Invoke nicht das UI-Update auslösen?

Ich versuche, ein UserControl wiederzuverwenden und auch einige Logiken auszuleihen, die den Fortschritt verfolgen. Ich werde versuchen, die Dinge zu vereinfachen. MyWindow.xaml enthält ein MyUserControl. MyUserControl hat seinen eigenen Fortschrittsanzeiger (Formatierung läuft..., Dateien werden kopiert..., etc.) und ich möchte diesen Fortschritt irgendwo im MyWindow-Formular spiegeln. Aber das Benutzersteuerelement hat einige Logiken, die ich nicht ganz verstehe. Ich habe gelesen und gelesen, aber ich verstehe den Dispatcher immer noch nicht. Hier ist eine Zusammenfassung der Logik im Benutzersteuerelement, die den Fortschritt aktualisiert.

this.Dispatcher.Invoke(DispatcherPriority.Input, (Action)(() =>
{
   DAProgressIndicator = InfiniteProgress.AddNewInstanceToControl(StatusGrid, new SolidColorBrush(new Color() { A = 170, R = 128, G = 128, B = 128 }), string.Empty);
                DAProgressIndicator.Message = MediaCardAdminRes.ActivatingCard;
                ActivateInProgress = true;
}));

Ich dachte, ich wäre klug und würde ein Ereignis zu MyUserControl hinzufügen, das in der Logik des ActivateInProgress-Eigenschaftssatzes aufgerufen würde.

   public bool ActivateInProgress 
   {
      get
      {
         return _activateInProgress;
      }
      set
      {
         _activateInProgress = value;
         if (ActivateInProgressHandler != null)
         {
            ActivateInProgressHandler(value);
         }
      }
   }

Ich setze den ActivateInProgressHandler im MyWindow-Konstruktor auf die folgende Methode, die die Eigenschaft des ViewModel setzt, die für den eigenen Fortschrittsanzeiger des Fensters verwendet wird.

private void SetActivation(bool activateInProgress)
{
   viewModel.ActivationInProgress = activateInProgress;
}

Der Fortschrittsanzeiger des Fensters ändert sich jedoch nie. Deshalb bin ich überzeugt, dass der Dispatcher.Invoke etwas tut, das ich nicht verstehe. Wenn ich eine MessageBox in die SetActivation-Methode setze, blockiert der Thread und der Fortschrittsanzeiger des Fensters wird aktualisiert. Ich verstehe grundlegende Threads, aber dieses ganze Dispatcher-Ding ist neu für mich. Was fehlt mir?

UPDATE: Es scheint jetzt zu funktionieren. Es stellte sich heraus, dass der Fortschritt so schnell aktualisiert wurde, dass er nie auf dem Bildschirm angezeigt wurde. Aber ich würde immer noch gerne verstehen, warum der Dispatcher.Invoke durchgeführt wurde (dies war vorhandener Code, den ich nicht geschrieben habe). Warum werden die Inhalte der Aktion nicht direkt mit dem Rest des *.xaml.cs-Codes ausgeführt?

1voto

Ray Burns Punkte 60870

Ihr letzter Absatz erwähnt zweimal Threads, was die Möglichkeit aufwirft, dass es einen oder mehrere Hintergrundthreads gibt. Da Sie jedoch nicht erwähnt haben, welche Threads in der Anwendung existieren, wie sie erstellt werden, wie sie interagieren usw., gehe ich vorerst davon aus, dass es nur einen Thread gibt.

Wenn der UI-Thread der einzige Thread ist, ist das Problem offensichtlich: Ihr UI-Thread ist damit beschäftigt, die laufende Aufgabe auszuführen, und nimmt sich keine Zeit, um das aktualisierte UI zu rendern. Wenn das das Problem ist, wird dies es wahrscheinlich beheben:

viewModel.ActivationInProgress = activateInProgress; 
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle,
                       new Action(() => {}));

Das BeginInvoke zwingt alle Dispatcher-Vorgänge über der Eingabepriorität abzuschließen, bevor der aktuelle Thread fortgesetzt wird.

0voto

Marthinus Punkte 743

Der Dispatcher arbeitet in einer Warteschlange. Es könnte also sein, dass der UI-Thread blockiert ist. Sie fügen mehr Arbeit in die Warteschlange über den Dispatcher hinzu, aber sie wird nie ausgeführt, weil der UI-Thread blockiert ist.

Vielleicht probieren Sie das:

DispatcherFrame _frame = new DispatcherFrame();
Dispatcher.PushFrame(_frame);

Dadurch wird Ihre Arbeit vor die bereits in der Warteschlange vorhandene Arbeit gestellt. Der UI-Thread wird also die Arbeit erledigen und dann wieder blockieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X