Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在后台获取数据并在准备就绪时用数据异步更新UI?_C#_Wpf_Mvvm_Async Await - Fatal编程技术网

C# 如何在后台获取数据并在准备就绪时用数据异步更新UI?

C# 如何在后台获取数据并在准备就绪时用数据异步更新UI?,c#,wpf,mvvm,async-await,C#,Wpf,Mvvm,Async Await,我选择了DataGrid中的对象,其行选择的更改在方法中处理(使用Interaction事件触发器InvokeCommandAction)。行表示现实生活中的对象,并具有许多属性 我首先设置一个行对应的属性,并在映射上突出显示对象,然后做一些其他的事情,最后调用async,一个获取对象属性并用这些属性刷新属性DataGrid的方法 SelectedObjectsViewModel.cs(包含SelectedObjects数据网格的UserControl的Viewmodel) ObjectProp

我选择了DataGrid中的对象,其行选择的更改在方法中处理(使用Interaction事件触发器InvokeCommandAction)。行表示现实生活中的对象,并具有许多属性

我首先设置一个行对应的属性,并在映射上突出显示对象,然后做一些其他的事情,最后调用async,一个获取对象属性并用这些属性刷新属性DataGrid的方法

SelectedObjectsViewModel.cs(包含SelectedObjects数据网格的UserControl的Viewmodel)

ObjectProperties.cs

    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%

我的问题是:如何做到这一点:

  • 选定对象DataGrid中的行选择和地图上的高亮显示将立即进行,根本不等待属性获取或属性DataGrid刷新
  • 选定对象DataGrid选择后的属性DataGrid刷新没有长时间延迟,因为它正在获取属性

  • 谢谢

    您应该在后台线程上执行任何长时间运行的方法。请注意,您无法访问后台线程上的任何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());
    }