WPF线程死锁
WPF Thread dead lock
我可以从你那里找到有用的答案吗?
我有 WPF 应用程序从 API 获取数据,当我触发以下代码时出现线程死锁
private List<Clinic> _clinics;
public List<Clinic> Clinics {
get { return _clinics; }
set { _clinics = value; OnPropertyChanged(); }
}
private Clinic _selectedClinic;
public Clinic SelectedClinic {
get { return _selectedClinic; }
set {
_selectedClinic = value; OnPropertyChanged();
if (value != null)
OnSelectClinic(value).Wait();
}
}
private async Task OnSelectClinic(Clinic clinic) {
try {
using (var request = await Client.GetAsync("URL OF API")) {
if (request.IsSuccessStatusCode){
StaffList = await request.Content.ReadAsAsync<Staff>();
}
var error = await request.Content.ReadAsStringAsync();
throw new Exception(error);
}
} catch (Exception e) {
Debug.WriteLine(e);
}
}
这是视图模型,Clinics、selectedClinic 和 Staff 绑定到 View.XAML
这里是 API 方法
[HttpGet("FindAllByClinic/{clinicId}")]
public async Task<IActionResult> FindAllByClinic(int clinicId) {
try {
return Ok(_mapper.Map<List<Staff>>(await _staffRepository
.FindAllBy(clinicId)));
} catch (Exception e) {
return BadRequest(e.Message);
}
}
这是 StaffRepository 方法:
public async Task<ICollection<Staff>> FindAllBy(int clinicId, int medicalPointId) {
var persons = await Context.Persons.FromSql("EXEC HR.GetPersonsByClinicId @ClinicId = 0," +
$"@EncryptPassword = '{DecryptPassword}'").ToListAsync();
var staffs = await Context.Staff
.Include(e => e.StaffClinics)
.ThenInclude(e => e.Clinic)
.ThenInclude(e => e.ClinicMedicalPoints)
.Where(e => e.StaffClinics.Any(c => c.ClinicId == clinicId
&& c.Clinic.ClinicMedicalPoints.Any(m => m.MedicalPointId
== medicalPointId)))
.ToListAsync();
foreach (var staff in staffs) {
staff.Person = persons.FirstOrDefault(e => e.Id == staff.PersonId);
}
return staffs;
}
问题是当我 select 来自组合框的诊所时,整个应用程序冻结
如果我有错误,任何人都可以给我建议或更正我的代码
public Clinic SelectedClinic {
get { return _selectedClinic; }
set {
_selectedClinic = value; OnPropertyChanged();
if (value != null)
OnSelectClinic(value).Wait();
}
}
这个setter超级糟糕,因为:
它用 OnPropertyChanged
引发了一个事件 - 没关系 - 但随后它继续在 setter 的主体中执行昂贵的操作。您已经在发起一个事件,也许应该订阅它并改为执行 OnSelectClinic
?
You're blocking on async
code, which is a sin that causes deadlocks。通常解决方案是用 await
s 替换阻塞等待,但在这种情况下,您需要重新设计,以便 属性 setter 不负责触发和等待此操作。
我可以从你那里找到有用的答案吗? 我有 WPF 应用程序从 API 获取数据,当我触发以下代码时出现线程死锁
private List<Clinic> _clinics;
public List<Clinic> Clinics {
get { return _clinics; }
set { _clinics = value; OnPropertyChanged(); }
}
private Clinic _selectedClinic;
public Clinic SelectedClinic {
get { return _selectedClinic; }
set {
_selectedClinic = value; OnPropertyChanged();
if (value != null)
OnSelectClinic(value).Wait();
}
}
private async Task OnSelectClinic(Clinic clinic) {
try {
using (var request = await Client.GetAsync("URL OF API")) {
if (request.IsSuccessStatusCode){
StaffList = await request.Content.ReadAsAsync<Staff>();
}
var error = await request.Content.ReadAsStringAsync();
throw new Exception(error);
}
} catch (Exception e) {
Debug.WriteLine(e);
}
}
这是视图模型,Clinics、selectedClinic 和 Staff 绑定到 View.XAML
这里是 API 方法
[HttpGet("FindAllByClinic/{clinicId}")]
public async Task<IActionResult> FindAllByClinic(int clinicId) {
try {
return Ok(_mapper.Map<List<Staff>>(await _staffRepository
.FindAllBy(clinicId)));
} catch (Exception e) {
return BadRequest(e.Message);
}
}
这是 StaffRepository 方法:
public async Task<ICollection<Staff>> FindAllBy(int clinicId, int medicalPointId) {
var persons = await Context.Persons.FromSql("EXEC HR.GetPersonsByClinicId @ClinicId = 0," +
$"@EncryptPassword = '{DecryptPassword}'").ToListAsync();
var staffs = await Context.Staff
.Include(e => e.StaffClinics)
.ThenInclude(e => e.Clinic)
.ThenInclude(e => e.ClinicMedicalPoints)
.Where(e => e.StaffClinics.Any(c => c.ClinicId == clinicId
&& c.Clinic.ClinicMedicalPoints.Any(m => m.MedicalPointId
== medicalPointId)))
.ToListAsync();
foreach (var staff in staffs) {
staff.Person = persons.FirstOrDefault(e => e.Id == staff.PersonId);
}
return staffs;
}
问题是当我 select 来自组合框的诊所时,整个应用程序冻结 如果我有错误,任何人都可以给我建议或更正我的代码
public Clinic SelectedClinic {
get { return _selectedClinic; }
set {
_selectedClinic = value; OnPropertyChanged();
if (value != null)
OnSelectClinic(value).Wait();
}
}
这个setter超级糟糕,因为:
它用
OnPropertyChanged
引发了一个事件 - 没关系 - 但随后它继续在 setter 的主体中执行昂贵的操作。您已经在发起一个事件,也许应该订阅它并改为执行OnSelectClinic
?You're blocking on
async
code, which is a sin that causes deadlocks。通常解决方案是用await
s 替换阻塞等待,但在这种情况下,您需要重新设计,以便 属性 setter 不负责触发和等待此操作。