首页 > 解决方案 > WPF Thread dead lock

问题描述

may i find useful answer from you. I have WPF application fetching the data from API, I have thread deadlock when i fire following code

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

this is the view model, and Clinics, selectedClinic and Staff are binding to View.XAML

and here is the API Method

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

Here is StaffRepository method :

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

the problem is when i select a clinic from combobox the entire application freeze Can any one give me suggestions or correct my code if I Have mistakes please

标签: c#wpfapixamlef-core-2.0

解决方案


public Clinic SelectedClinic {
            get { return _selectedClinic; }
            set {
                _selectedClinic = value; OnPropertyChanged();
                if (value != null)
                    OnSelectClinic(value).Wait();
            }
        }

这个二传手非常糟糕,因为:

  1. 它引发了一个事件OnPropertyChanged- 没关系 - 但它继续在 setter 主体中执行昂贵的操作。您已经在发起一个事件,也许应该订阅它并执行它OnSelectClinic

  2. 您正在阻塞async代码,这是导致死锁的罪过。通常解决方案是用awaits 替换阻塞等待,但在这种情况下,您需要重新设计,以便属性设置器不负责触发和等待此操作。


推荐阅读