C# 如何在后台获取数据并在准备就绪时用数据异步更新UI?
我选择了DataGrid中的对象,其行选择的更改在方法中处理(使用Interaction事件触发器InvokeCommandAction)。行表示现实生活中的对象,并具有许多属性 我首先设置一个行对应的属性,并在映射上突出显示对象,然后做一些其他的事情,最后调用async,一个获取对象属性并用这些属性刷新属性DataGrid的方法 SelectedObjectsViewModel.cs(包含SelectedObjects数据网格的UserControl的Viewmodel) ObjectProperties.csC# 如何在后台获取数据并在准备就绪时用数据异步更新UI?,c#,wpf,mvvm,async-await,C#,Wpf,Mvvm,Async Await,我选择了DataGrid中的对象,其行选择的更改在方法中处理(使用Interaction事件触发器InvokeCommandAction)。行表示现实生活中的对象,并具有许多属性 我首先设置一个行对应的属性,并在映射上突出显示对象,然后做一些其他的事情,最后调用async,一个获取对象属性并用这些属性刷新属性DataGrid的方法 SelectedObjectsViewModel.cs(包含SelectedObjects数据网格的UserControl的Viewmodel) ObjectProp
public void SetAttributeObjectNoRefresh(NetObject netObject)
{
_attributeObject = netObject;
}
public IEnumerable<PropertyRow> GetAttributeObjectAttributes()
{
if (_attributeObject != null)
{
List<string> fieldNames = new List<string>();
List<string> visibleNames = new List<string>();
List<string> values = new List<string>();
/* get properties for _attributeObject from db and
* process in native code */
var properties = GetPropertiesFilterAndSort(fieldNames, visibleNames, values, _attributeObject);
foreach (var property in properties)
{
yield return property;
}
}
}
public void SetAttributeObjectNoRefresh(NetObject NetObject)
{
_attributeObject=netObject;
}
public IEnumerable GetAttributeObject属性()
{
如果(_attributeObject!=null)
{
列表字段名=新列表();
List visibleNames=新列表();
列表值=新列表();
/*从数据库中获取_attributeObject的属性,并
*本机代码中的进程*/
var properties=GetPropertiesFilterAndSort(字段名、visibleNames、值、_attributeObject);
foreach(属性中的var属性)
{
收益性;
}
}
}
但是,在完成高亮显示等其他操作后,包含对象属性的DataGrid将被刷新,这会有高达1,2秒的延迟。我想在知道对象后立即开始抓取,继续突出显示等操作,最后异步启动SelectedObjectsChanged以使用抓取的属性数据来刷新DataGrid
获取包括数据库获取和一些处理。根据环境和设置,数据库获取时间最多可以达到80%,但只能达到50%
我的问题是:如何做到这一点:
谢谢 您应该在后台线程上执行任何长时间运行的方法。请注意,您无法访问后台线程上的任何UI元素,因此基本上需要启动一个新任务来获取数据,然后在任务完成后处理任何UI内容 下面是一个在后台线程上执行
GetAttributeObjectAttributes()
方法的基本示例:
private ICollectionView _ojectInfoItems;
public ICollectionView ObjectInfoItems
{
get { return myVar; }
set { myVar = value; OnPropertyChanged(); }
}
public ObjectViewModel()
{
Task.Factory.StartNew(() =>
{
return ObjectProperties.Instance.GetAttributeObjectAttributes();
}).ContinueWith(task =>
{
ObjectInfoItems = CollectionViewSource.GetDefaultView(task.Result);
}, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}
请注意,ObjectViewModel
类应实现该接口,并在设置数据绑定的ObjectInfoItems
属性时引发PropertyChanged
事件
编辑:
基于您的评论的另一个示例:
public void SelectedObjectsGridSelectionChangedCommand(object parameter)
{
object data = null;
IList selectedRows = parameter as IList;
if (selectedRows.Count == 1)
data = (SelectedNetObjectBindingSource)selectedRows[0]).Data;
Task.Factory.StartNew(() =>
{
ObjectProperties.Instance.SetAttributeObjectNoRefresh(null);
Parallel.Invoke(
() => SetAttributeObjectExtraHightlight<SelectedNetObjectBindingSource>(selectedRows),
() => DoSomeOtherStuff(selectedRows));
}).ContinueWith(task =>
{
((ObjectViewModel)MyApp.ViewModels["Shared.Panels.Object"]).SelectedObjectsChanged();
}, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}
public void SelectedObjectsGridSelectionChangedCommand(对象参数)
{
对象数据=null;
IList selectedRows=参数为IList;
如果(selectedRows.Count==1)
数据=(SelectedNetObjectBindingSource)selectedRows[0])。数据;
Task.Factory.StartNew(()=>
{
ObjectProperties.Instance.SetAttributeObjectNoRefresh(null);
并行调用(
()=>SetAttributeObject超高亮度(selectedRows),
()=>DoSomeOtherStuff(selectedRows));
}).ContinueWith(任务=>
{
((ObjectViewModel)MyApp.ViewModels[“Shared.Panels.Object”])。选择对象设置();
},System.Threading.CancellationToken.None,TaskContinuationOptions.None,TaskScheduler.FromCurrentSynchronizationContext());
}
?@Sinatr:我认为这和我现在的情况一样有效。所有这些都发生在UI线程中?我需要另一个线程来获取数据。那么在哪里获取数据呢?在后台线程上调用此方法…@mm8:获取属性的方法是GetAttributeObjectAttributes。如果我知道怎么做,我不是来问怎么做的。如果你需要,请写一个完整的答案。所以执行GetAttributeObjectAttributes需要一点时间,你想在后台线程上运行吗?@mm8:这应该发生在SelectedObjectsGridSelectionChangedCommand(请参见问题)中,我想启动后台线程,然后设置要执行的AttributeObject ExtraHightLight和DoSomeOtherStuff,当后台线程返回结果时,将异步执行DataGrid刷新,以便UI响应。现在我不知道如何执行这两个方法,因为后台线程继续刷新。如果不是这样的话,这个连续体真的很酷。请注意,启动任务的推荐方法是task.Run
(从.NET 4.5开始)。只有在绝对必要时才建议使用Task.Factory.StartNew
,请参见。@matti:我不明白。任务本身中的所有代码都在后台线程上运行,而ContinueWith中的所有代码都在UI线程上运行。是。那很好。但在我的问题中,我需要调用SetAttributeObjectExtraHightlight和DoSomeOtherStuff,我希望它们与后台线程并行运行。如何完成?如果您在SelectedObjectsGridSelectionChangedCommand中使用代码发布答案,那么使用同一种语言会容易得多,这是这里的真实情况。谢谢
private ICollectionView _ojectInfoItems;
public ICollectionView ObjectInfoItems
{
get { return myVar; }
set { myVar = value; OnPropertyChanged(); }
}
public ObjectViewModel()
{
Task.Factory.StartNew(() =>
{
return ObjectProperties.Instance.GetAttributeObjectAttributes();
}).ContinueWith(task =>
{
ObjectInfoItems = CollectionViewSource.GetDefaultView(task.Result);
}, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}
public void SelectedObjectsGridSelectionChangedCommand(object parameter)
{
object data = null;
IList selectedRows = parameter as IList;
if (selectedRows.Count == 1)
data = (SelectedNetObjectBindingSource)selectedRows[0]).Data;
Task.Factory.StartNew(() =>
{
ObjectProperties.Instance.SetAttributeObjectNoRefresh(null);
Parallel.Invoke(
() => SetAttributeObjectExtraHightlight<SelectedNetObjectBindingSource>(selectedRows),
() => DoSomeOtherStuff(selectedRows));
}).ContinueWith(task =>
{
((ObjectViewModel)MyApp.ViewModels["Shared.Panels.Object"]).SelectedObjectsChanged();
}, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}