Warten auf Beenden einer Await-Funktion

  • WPF MVVM
  • .NET (FX) 4.5–4.8

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von kafffee.

    Warten auf Beenden einer Await-Funktion

    Hallo allerseits :)

    Ich steh grad vor einem grösseren Problem, und zwar möchte ich einen Registrierungsvorgang anstossen als allererstes wenn mein Programm lädt. Meine Application_Startup in der Application.xaml.vb seiht so aus:

    VB.NET-Quellcode

    1. ​Private Sub Application_Startup(sender As Object, e As StartupEventArgs) Handles Me.Startup
    2. ViewModel.Services.ServiceContainer.Instance.AddService(Of ViewModel.Services.IMainWindowService)(New Services.MainWindowService)
    3. ...
    4. ViewModel.Services.ServiceContainer.GetService(Of ViewModel.Services.IMainWindowService).OpenWindow(1000, 500, "Hauptfenster", Nothing, Me) 'hier wird das Hauptanwendungsfenster geöffnet
    5. MessageBox.Show("Application_Startup wurde ausgeführt")
    6. End Sub


    In der MainWindow.xaml hab ich Folgendes, um beim Laden den Registrierungsvorgang anszustossen. Dies muss ich auf diese Weise tun, und nicht einfach in der Application_Startup, weil sonst das Programm einfriert...

    XML-Quellcode

    1. <b:Interaction.Triggers>
    2. <b:EventTrigger EventName="Loaded">
    3. <b:InvokeCommandAction
    4. CommandParameter="{Binding}"
    5. Command="{Binding Startvorgang}"/>
    6. </b:EventTrigger>
    7. </b:Interaction.Triggers>
    8. <Window.DataContext>
    9. <viewmodel:MainViewModel/>
    10. </Window.DataContext>​


    Und zwar dann so:

    VB.NET-Quellcode

    1. Private _Startvorgang As ICommand
    2. Public ReadOnly Property Startvorgang As ICommand
    3. Get
    4. If _Startvorgang Is Nothing Then _Startvorgang = New ViewModel.Instrastructure.RelayCommand(AddressOf Startvorgang_Execute)
    5. Return _Startvorgang
    6. End Get
    7. End Property
    8. Private Async Sub Startvorgang_Execute(obj As Object)
    9. MessageBox.Show("Registrierung wird gestartet")
    10. Dim MeineRegistrierung As New Registrierung
    11. Await MeineRegistrierung.Start
    12. MessageBox.Show("Registrierung wurde abgeschlossen")
    13. WeitereItialisierungen() 'hier soll weiters initialisiert werden
    14. End Sub


    Funktioniert auch soweit, bis auf die Tatsache, dass ich dann beim weiteren Initialisieren meines Programms dann auf ein Haufen Nullverweisausnahmen stosse.

    Bis jetzt hatte ich diese Initialisierung im Konstruktor eines meiner ViewModels, das per DataTemplate mit einer View auf dem MainWindow verknüpft ist. Habs getestet, dieser Konstruktor wird noch vor "Application_Startup wurde ausgeführt" und vor "Registrierung wird gestartet" ausgeführt.

    Meine Vermutung ist, dass sich die Application_Startup und der Aufruf aus dem MainViewModel in dei Quere kommen.

    Gibt es einen Weg, auf Await MeineRegistrierung.Start zu warten, bis vollständig beendet?

    Denn bisher bekomme ich die MessageBoxen in dieser Reihenfolge:

    "Registrierung wird gestartet"
    Dann diese:
    "Application_Startup wurde ausgeführt"

    Ich möchte aber, dass folgende Reihenfolge eingehalten wird:
    "Registrierung wird gestartet"
    "Registrierung wurde abgeschlossen"
    "Application_Startup wurde ausgeführt", also dass da gewartet wird
    Mit Await bei Await MeineRegistrierung.Start sagst du ja bereits, dass er warten soll. Es ist also vermutlich Start von MeineRegistrierung nicht richtig implementiert. Da diese Methode sagt, er ist fertig, obwohl er es noch gar nicht ist. Wie ist diese Methode, implementiert?
    Also im Testprogramm funktioniert es, nur halt nur nicht im großen Projekt.
    Ich muss dazu sagen, dass diese Methode WeitereInitialisierungen() bisher im Konstruktor des besagten ViewModels zu finden war, da hat es noch funktioniert. Sie hängt auch nicht vom Ergebnis vor .Start ab, sondern hat vielmehr gar nichts zu tun damit.
    Zudem wird ja offensichtlich dieser Konstruktor noch vor dem anderen Kram aufgerufen. Wenn es jetzt genau andersrum wäre würde ich es ja verstehen, ist es aber nicht.
    Mich wunderts halt dass "Applikation_Startup" zwischen "Registrierung wird gestartet" und "Registrierung wurde abgeschlossen" auftaucht und nicht komplett davor oder danach...
    Wenn du mehr Code brauchst gerne melden
    Probier es mal ohne MessageBoxen, sondern mit Dateiausgabe oder Console.WriteLine. Probier auch mal, ob die Reihenfolge ohne Async/Await so stattfindet, wie Du es erwartest.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Mir scheint, dir ist die tatsächliche Funktion von Await noch nicht ganz klar. Das Wort 'Await' ist auch bisserl missverständlich, weil es geht um Nebenläufigkeit (Async) - also darum, graden nicht zu warten.
    Und zwar returnt eine Async-Methode am Await-Schlüsselwort sofort. Das Proggi läuft also weiter, ohne dass die Async-Methode den Code nach dem Await ausgeführt hätte.
    Später dann - wann genau ist unbestimmt - erfolgt eine Art Callback, und der Code nach dem Await-Keyword wird nachgeholt.

    kafffee schrieb:

    Gibt es einen Weg, auf Await MeineRegistrierung.Start zu warten, bis vollständig beendet?
    Ganz einfach: Lass Async/Await weg.
    Alles klar Leute danke für die Tipps. Hab zur Sicherheit mal den Aufruf von MeineRegistrierung komplett rausgenommen und hab den Fehler mit den Nullverweisausnahmen immer noch, also zumindest schon mal ein Schritt weiter beim Debuggen, darum ging's mir ja... Die Nullverweisausnahmen konnte ich auch beheben, jetzt hab ich dafür ein anderes Problem, da werd ich bei Bedarf aber nen separaten Thread aufmachen.