Wpf ToListSync冻结用户界面
我有一个叫病人的模型:Wpf ToListSync冻结用户界面,wpf,entity-framework,async-await,Wpf,Entity Framework,Async Await,我有一个叫病人的模型: [Key] public Guid Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } 我的存储库返回所有患者(行数为1): 你知道为什么吗 谢谢所以我解决了这个问题,我正在使用callMethodOnLoadBehavior.cs。由于此行为不是作为等待任务执行的,因此它会阻塞UI 我必须做的是调用存储库调用GetPatientsAsyn
[Key]
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
我的存储库返回所有患者(行数为1):
你知道为什么吗
谢谢所以我解决了这个问题,我正在使用callMethodOnLoadBehavior.cs。由于此行为不是作为
等待任务执行的,因此它会阻塞UI
我必须做的是调用存储库调用GetPatientsAsync
我将其包装在任务中。运行(()=>_repository.GetPatientsAsync())代码>
如果有更好的方法使用反射并能够调用wait
,请告诉我
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
}
公共类CallMethodOnLoadBehavior:行为
{
#区域属性
公共字符串方法名
{
获取{return(string)GetValue(MethodNameProperty);}
set{SetValue(MethodNameProperty,value);}
}
//使用DependencyProperty作为MethodName的备份存储。这将启用动画、样式设置、绑定等。。。
公共静态只读DependencyProperty MethodNameProperty=
Register(“MethodName”、typeof(string)、typeof(CallMethodOnLoadBehavior)、newpropertyMetadata(null));
公共对象目标对象
{
获取{返回GetValue(TargetObject属性);}
set{SetValue(TargetObjectProperty,value);}
}
//使用DependencyProperty作为TargetObject的后备存储。这将启用动画、样式设置、绑定等。。。
公共静态只读从属属性TargetObjectProperty=
Register(“TargetObject”、typeof(object)、typeof(CallMethodOnLoadBehavior)、newpropertyMetadata(null));
#端区
#区域方法
受保护的覆盖无效附加()
{
base.onatached();
AssociatedObject.Loaded+=已加载;
}
已加载专用void(对象发送方,RoutedEventArgs e)
{
if(AssociatedObject==null | | string.IsNullOrWhiteSpace(MethodName)| | TargetObject==null)返回;
var minfo=TargetObject.GetType().GetTypeInfo().GetDeclaredMethod(方法名);
if(minfo==null)返回;
Invoke(TargetObject,null);
}
#端区
}
您可以尝试将属性分配封送回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);
}
}
LoadPatients
从何处调用?它是从视图调用的,通过一个行为,请查看我下面关于解决问题的帖子。事实并非如此,当我逐步查看代码时,我清楚地看到在调用.toListSync()后有一个长时间的暂停。在查询之前禁用代理生成和懒散加载也不能解决问题。将其封送回UI也不能解决问题?因此这是我的实际代码:public async void LoadPatients(){Patients=wait Task.Run(()=>_repository.GetPatientsAsync());if(Patients!=null)SelectedPatient=Patients.FirstOrDefault();}
之所以有效,是因为我将异步getpatients包装在task.run中。请参阅下面我的回答,以了解有关我如何准确致电患者的更多详细信息。
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
}
public async Task LoadPatients()
{
var s = await _repository.GetPatientsAsync();
if (Patients != null)
{
var patient = Patients.FirstOrDefault();
Application.Dispatcher.Current.Invoke(() => SelectedPatient = patient);
}
}