2017-11-15 2 views
-2

Ich habe zwei Combobox-Steuerelemente auf meiner Seite, gebunden an eine ObservableCollection <Hersteller> und ObservableCollection <Treiber>.Anwendung hängt an Async-Methode warten

Wenn die Seite geladen ist, wird OnWindowLoaded() ausgeführt. Wenn der Setter der Eigenschaft Vendor ausgelöst wird, wird OnVendorPropertyChanged ausgeführt. Wenn OnWindowLoaded() beendet wird, werden Vendor und Driver korrekt eingerichtet.

jedoch, wenn ich den Anbieter wechseln, wartet die Anwendung auf der Linie

LoadDriversAsync(Vendor.DCP).Wait(); 

Wie kann ich dieses Problem beheben?

private async void OnWindowLoaded() 
    { 
     Debug.WriteLine("Enter OnWindowLoaded"); 
     await LoadVendorsAsync(); 
     await System.Threading.Tasks.Task.Run(() => { Vendor = Vendors.FirstOrDefault(); }); 
     await System.Threading.Tasks.Task.Run(() => { Driver = Drivers.FirstOrDefault(); }); 
     Debug.WriteLine("Leave OnWindowLoaded"); 
    } 

    private Vendor _vendor; 
    public Vendor Vendor 
    { 
     get 
     { 
      return _vendor; 
     } 

     set 
     { 
      if (value != _vendor) 
      { 
       var oldVendor = new Vendor(); 
       oldVendor = _vendor; 
       _vendor = value; 
       RaisePropertyChanged(nameof(Vendor), oldVendor, Vendor, true); 
      } 
     } 
    } 


    /// <summary> 
    /// Raised when Vendor property is changed 
    /// </summary> 
    /// <param name="vendor"></param> 
    private void OnVendorPropertyChanged(PropertyChangedMessage<Vendor> vendor) 
    { 
     Debug.WriteLine("Enter OnVendorPropertyChanged"); 

      //application hangs when vendor is changed 
      LoadDriversAsync(Vendor.DCP).Wait(); 
      Debug.WriteLine("Leave OnVendorPropertyChanged"); 
    } 

    private async System.Threading.Tasks.Task LoadVendorsAsync() 
    { 
      Debug.WriteLine("Enter LoadVendorsAsync"); 
      //load the vendors, don't return data 
      Debug.WriteLine("Leave LoadVendorsAsync"); 

    } 

     private Vendor _vendor; 
    public Vendor Vendor 
    { 
     get 
     { 
      return _vendor; 
     } 

     set 
     { 
      if (value != _vendor) 
      { 
       var oldVendor = new Vendor(); 
       oldVendor = _vendor; 
       _vendor = value; 
       RaisePropertyChanged(nameof(Vendor), oldVendor, Vendor, true); 
      } 
     } 
    } 

    ObservableCollection<Vendor> _vendors = new ObservableCollection<Vendor>(); 
    public ObservableCollection<Vendor> Vendors 
    { 
     get 
     { 
      return _vendors; 
     } 

     set 
     { 
      if (_vendors != value) 
      { 
       var oldVendors = _vendors; 
       _vendors = value; 
       RaisePropertyChanged(nameof(Vendors), oldVendors, Vendors, true); 
      } 

     } 
    } 

private async System.Threading.Tasks.Tas LoadDriversAsync(Objects.Vendor Vendor) 
    { 

      Debug.WriteLine("Enter LoadDriversAsync"); 
//load data, don't return 

      Debug.WriteLine("Leave LoadDriversAsync"); 
      RaisePropertyChanged(nameof(Drivers), oldDrivers, Drivers, true); 
     } 

    } 

Ausgabe

Enter OnWindowLoaded 
Enter LoadVendorsAsync 
Leave LoadVendorsAsync 
Enter OnVendorPropertyChanged 
Enter LoadDriversAsync 
Leave LoadDriversAsync 
Leave OnVendorPropertyChanged 
Leave OnWindowLoaded 

Edited

Nach Boo Ratschläge nicht helfen. Die Anwendung bleibt beim Lieferantenwechsel blockiert.

enter image description here

Nach @Frederik Gheysels Rat hat nicht geholfen.

Ausgabe

Enter OnWindowLoaded 
Enter LoadVendorsAsync 
Enter OnVendorPropertyChanged 
Enter LoadDriversAsync 
Leave OnWindowLoaded 
Leave LoadDriversAsync 
Leave OnVendorPropertyChanged 
+3

Ich vermute, dass ein UI Dead-Lock aufrufen, versuchen Task.Run (() => LoadDriversAsync (Vendor.DCP)). Wait(); – Boo

+2

Google "warten task.run". Der erste Treffer ist gut. –

+0

@Boo Danke, aber das hat nicht geholfen – BertAR

Antwort

1

Sie werden fast nie warten wollen, wenn Sie asynchrone Methoden haben.

Hier ist ein Beispiel, wie Deadlock

  1. Asynchron-Methode
  2. Asynchron-Methode aufgerufen passieren kann, tritt ein und Haupt-Thread warten läuft etwas anderes
  3. Hauptthread
  4. Warte Aufruf einer Methode wait() ausführt, wartet auf async zu beenden
  5. async wartet auf Haupt-Thread, um frei zu werden
  6. DEAD LOCK

so, wenn es möglich ist, das Verfahren zu ändern, in dem Sie .wait() auf sein async und Anruf warten darauf

0

Sie erleben eine Sackgasse.

Warum verwenden Sie .Wait() für diesen Methodenaufruf?

Sie sollten Ihre Aufrufmethode asynchron machen und die Aufgabe abwarten.

+0

Ich habe versucht, Ihren Code, aber dann ist mein Treiber nicht gesetzt, wenn OnWindowLoaded() – BertAR