应用程序挂起等待异步方法
Application hangs on wait async method
我的页面上有两个组合框控件,绑定到 ObservableCollection 和 ObservableCollection。
加载页面时,将执行 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 的建议没有帮助。更改供应商时应用程序仍然阻塞。
遵循@Frederik Gheysel 的建议没有帮助。
输出
Enter OnWindowLoaded
Enter LoadVendorsAsync
Enter OnVendorPropertyChanged
Enter LoadDriversAsync
Leave OnWindowLoaded
Leave LoadDriversAsync
Leave OnVendorPropertyChanged
您遇到了死锁。
为什么在该方法调用中使用 .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");
}
当你有异步方法时,你几乎永远不想调用 wait。
这是一个如何发生死锁的例子
- 调用了异步方法
- 异步方法进入等待状态,主线程运行其他东西
- 主线程执行一个调用wait()的方法
- wait 正在等待异步完成
- async 正在等待主线程空闲
- 死锁
因此,如果可能,请将调用 .wait() 的方法更改为异步并在其上调用 await
我的页面上有两个组合框控件,绑定到 ObservableCollection
加载页面时,将执行 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 的建议没有帮助。更改供应商时应用程序仍然阻塞。
遵循@Frederik Gheysel 的建议没有帮助。
输出
Enter OnWindowLoaded
Enter LoadVendorsAsync
Enter OnVendorPropertyChanged
Enter LoadDriversAsync
Leave OnWindowLoaded
Leave LoadDriversAsync
Leave OnVendorPropertyChanged
您遇到了死锁。
为什么在该方法调用中使用 .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");
}
当你有异步方法时,你几乎永远不想调用 wait。
这是一个如何发生死锁的例子
- 调用了异步方法
- 异步方法进入等待状态,主线程运行其他东西
- 主线程执行一个调用wait()的方法
- wait 正在等待异步完成
- async 正在等待主线程空闲
- 死锁
因此,如果可能,请将调用 .wait() 的方法更改为异步并在其上调用 await