-2

I've got two combobox controls on my page, binded to a ObservableCollection<Vendor> and ObservableCollection<Driver>.

When the page is loaded the OnWindowLoaded() is executed. When the setter of the property Vendor is triggered, OnVendorPropertyChanged is executed. When OnWindowLoaded() finishes, Vendor and Driver is being set correctly.

However when I change the Vendor, the application waits on the line

LoadDriversAsync(Vendor.DCP).Wait();

How can I fix this?

    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);
        }

    }

Output

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

Edited

Following Boo advice did not help. Application still blocks when changing vendor.

enter image description here

Following @Frederik Gheysels advice did not help.

Output

Enter OnWindowLoaded
Enter LoadVendorsAsync
Enter OnVendorPropertyChanged
Enter LoadDriversAsync
Leave OnWindowLoaded
Leave LoadDriversAsync
Leave OnVendorPropertyChanged
BertAR
  • 425
  • 3
  • 18

2 Answers2

1

You will almost never want to call wait when you have async methods.

Here is an example how deadlock can happen

  1. async method called
  2. async method enters wait and main thread runs something else
  3. main thread executes a method calling wait()
  4. wait is waiting for async to finish
  5. async is waiting for main thread to become free
  6. DEAD LOCK

so if it is possible, change the method where you are calling .wait() on to be async and call await on it

Steve
  • 11,696
  • 7
  • 43
  • 81
0

You're experiencing a deadlock.

Why do you use .Wait() on that method call ?

You should make your calling method async and await the Task.

    private async void OnVendorPropertyChanged(PropertyChangedMessage<Vendor> vendor)
    {
         Debug.WriteLine("Enter OnVendorPropertyChanged");

         //application hangs when vendor is changed
         await LoadDriversAsync(Vendor.DCP);
         Debug.WriteLine("Leave OnVendorPropertyChanged");
    }
Frederik Gheysels
  • 56,135
  • 11
  • 101
  • 154