应用程序挂起等待异步方法

时间:2017-11-15 16:14:00

标签: c# asynchronous async-await task-parallel-library

我的页面上有两个组合框控件,绑定到ObservableCollection< Vendor>和ObservableCollection< Driver>。

加载页面时,执行OnWindowLoaded()。 触发属性Vendor的setter时,将执行OnVendorPropertyChanged。 当OnWindowLoaded()完成时,正确设置了供应商和驱动程序。

但是,当我更改供应商时,应用程序会在行

上等待
LoadDriversAsync(Vendor.DCP).Wait();

我该如何解决这个问题?

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

    }

输出

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

被修改

遵循Boo建议没有帮助。更换供应商时,应用程序仍会阻止。

enter image description here

关注@Frederik Gheysels的建议没有帮助。

输出

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

2 个答案:

答案 0 :(得分:1)

当您使用异步方法时,几乎不会想要等待。

这是一个如何发生死锁的例子

  1. async方法名为
  2. 异步方法进入等待,主线程运行其他东西
  3. 主线程执行一个调用wait()
  4. 的方法
  5. 等待异步完成
  6. async正在等待主线程变为空闲
  7. DEAD LOCK
  8. 所以,如果可能的话,将调用.wait()的方法更改为async并调用await

答案 1 :(得分:0)

您遇到了僵局。

为什么在该方法调用上使用.Wait()?

你应该让你的调用方法异步并等待任务。

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