2016-05-13 14 views
0

Ich habe eine Seite in meiner Anwendung, die angezeigt wird, und ich möchte eine potenziell lange laufende Hintergrundoperation durchführen. Während dieser Vorgang ausgeführt wird, sollte eine andere Ansicht angezeigt werden, und wenn sie abgeschlossen ist, sollte die Region zurück zu ihrer früheren Ansicht navigiert werden. Wenn irgendetwas schief geht, sollte die Navigation zu einer anderen Ansicht gehen.Navigieren von Hintergrundoperation

Um dies zu veranschaulichen, nehme ich eine Klasse, und einen ICommand in seinem Konstruktor gesetzt:

SomeAction = new DelegateCommand(() => 
{ 
    _regionManager.RequestNavigate("MyTarget", nameof(SomeProgressPage)); 

    Task.Run(() => 
    { 
     DoSomeWork(); 
    }); 
}); 

Die Aufgabe selbst mit etwas potentiell lang andauernde betroffen ist; Sobald es fertig ist, sollte es zu einem bedingten Ziel navigieren.

private void SomeWork() 
{ 
    try 
    { 
     // Do Work 
     // ... 

     // Return when done. 
     _regionManager.RequestNavigate("MyTarget", nameof(SomePage)); 
    } 
    catch 
    { 
     _regionManager.RequestNavigate("MyTarget", nameof(SomeErrorPage)); 
    } 
} 

Während ich durch das im Debug-Schritt kann und in denen keine Fehler auf dem Weg, RequestNavigation scheint keine Wirkung zu haben, wenn sie von einem anderen Thread aufgerufen, noch übernimmt sie eine Ausnahme werfen. Ich navigiere zu "SomeProgressPage", die Aufgabe wird ausgeführt, und basierend auf dem Ergebnis kann die Ausführung der RequestNavigation folgen - dann nichts.

Ich habe auch versucht, diese Navigation über Veranstaltungen durchzuführen, wie zum Beispiel:

eventAggregator.GetEvent<NavigationRequestEvent>().Subscribe(x => 
{ 
    regionManager.RequestNavigate(x.Target, x.Destination, x.Parameters); 

}, ThreadOption.UIThread); 

In diesem Fall wird der Teilnehmer nicht einmal aufgerufen, wenn das Ereignis veröffentlicht wird.

Ich konnte keine glaubwürdigen Ressourcen finden, mit denen ich von meinem Googlen aus damit umgehen konnte, und ich hatte keine Verbindung zur Quelle und konnte nicht über Prism debuggen. Wie sollte diese Art von Funktion am besten bei der Verwendung von Prism implementiert werden?

Antwort

1

Die Sache ist, dass Ausnahmen in einer Task, die nicht erwartet wird, von der Task aggregatedException Handler geschluckt werden. Sie können auf die von einer Task ausgelösten Ausnahmen zugreifen, indem Sie die Eigenschaft Task.Exception überprüfen. nur lauched

 Task.Run(() => 
     { 
      //DoSomeWork(); 
     }) 
     .ContinueWith((t) => 
     { 
      // Return when done. 
      _regionManager.RequestNavigate("MyTarget", nameof(SomePage)); 
     }) 
     .ContinueWith((t) => 
     { 
      _regionManager.RequestNavigate("MyTarget", nameof(SomeErrorPage)); 
     }, TaskContinuationOptions.OnlyOnFaulted); 

Der zweite ContinueWith wird, wenn die Aufgabe fehlerhaft ist (was bedeutet, dass die Aufgabe, eine Ausnahme ausgelöst hat): Sie können auch die folgenden tun.

1

Wenn Sie ein neues Fenster von einem anderen Thread öffnen möchten, müssen Sie den aktuellen Dispatcher aufrufen.

private void SomeWork() 
      { 
       try 
       { 
        // Do Work 
        // ... 

        // Return when done. 
        App.Current.Dispatcher.Invoke((Action)delegate 
        { 

        _regionManager.RequestNavigate("MyTarget", nameof(SomePage)); 

        }); 
       } 
       catch 
       { 
        App.Current.Dispatcher.Invoke((Action)delegate 
        { 

        _regionManager.RequestNavigate("MyTarget", nameof(SomeErrorPage)); 

        }); 
       }   
     }