我有一个名为Patient的模型:
[Key]
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
我的存储库返回所有患者(行数为1):
public async Task<List<Patient>> GetPatientsAsync()
{
//await Task.Delay(1).ConfigureAwait(false);
return await _context.Patients.ToListAsync();
}
运行该代码会冻结UI,但如果我删除GetPatientsAsync()中的注释,则UI会在返回所有患者(同样只返回1行)时响应。
在我的ViewModel端,我这样称呼它:
public async Task LoadPatients()
{
var s = await _repository.GetPatientsAsync();
//if (Patients != null) SelectedPatient = Patients.FirstOrDefault();
}
任何线索,为什么会这样?
由于
答案 0 :(得分:0)
所以我解决了这个问题,我正在使用CallMethodOnLoadBehaviour.cs。由于此行为未作为await Task
执行,因此它阻止了UI。
我需要做的就是调用存储库GetPatientsAsync
我在Task.Run(() => _repository.GetPatientsAsync());
内部。
如果有更好的方法可以使用反射并且能够拨打await <Task>
,请告诉我们!
public class CallMethodOnLoadBehavior : Behavior<FrameworkElement>
{
#region Properties
public string MethodName
{
get { return (string)GetValue(MethodNameProperty); }
set { SetValue(MethodNameProperty, value); }
}
// Using a DependencyProperty as the backing store for MethodName. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MethodNameProperty =
DependencyProperty.Register("MethodName", typeof(string), typeof(CallMethodOnLoadBehavior), new PropertyMetadata(null));
public object TargetObject
{
get { return GetValue(TargetObjectProperty); }
set { SetValue(TargetObjectProperty, value); }
}
// Using a DependencyProperty as the backing store for TargetObject. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TargetObjectProperty =
DependencyProperty.Register("TargetObject", typeof(object), typeof(CallMethodOnLoadBehavior), new PropertyMetadata(null));
#endregion
#region Methods
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
if (AssociatedObject == null || string.IsNullOrWhiteSpace(MethodName) || TargetObject == null) return;
var minfo = TargetObject.GetType().GetTypeInfo().GetDeclaredMethod(MethodName);
if (minfo == null) return;
minfo.Invoke(TargetObject, null);
}
#endregion
}
答案 1 :(得分:0)
您可以尝试将您的属性分配封送回UI线程。我不确定EF的工作原理。我的直觉告诉我ToListAsync()
是延迟加载的,这意味着当你调用FirstOrDefault()
时,返回的值仍然是从后台线程获取的(因为你等待存储库中的调用)并且你尝试分配和调用主线程OnPropertyChanged
。
public async Task LoadPatients()
{
var s = await _repository.GetPatientsAsync();
if (Patients != null)
{
var patient = Patients.FirstOrDefault();
Application.Dispatcher.Current.Invoke(() => SelectedPatient = patient);
}
}