UWP TreeView UI Deadlock - loading time from less than 1 sec to more than 10 sec - first run against new run

有些话、适合烂在心里 提交于 2020-04-30 07:14:52

问题


I have a major performance issue on a TreeView both in terms of loading time as well as a deadlock of the UI.

        private async Task LoadTreeAsync()
        {
            List<VPazVisit> aList = new List<VPazVisit>();
            if (_sorting == "")
            {
                _sorting = await ApplicationData.Current.LocalSettings.ReadAsync<string>("TreeViewSort");
            }

            treeView.Visibility = Visibility.Collapsed;
            Patients.Clear();
            switch (_sorting)
            {
                default:
                case "DescDate":
                    aList = await Task.Run(() => App.gDataContext.Cache.VPazVisit
                        .OrderByDescending(b => b.Data).ThenBy(b => b.Cognome).ThenBy(b => b.Nome)
                        .ToList());
                    break;
                case "AsceDate":
                    aList = await Task.Run(() => App.gDataContext.Cache.VPazVisit
                        .OrderBy(b => b.Data).ThenBy(b => b.Cognome).ThenBy(b => b.Nome)
                        .ToList());
                    break;
                case "DescAlph":
                    aList = await Task.Run(() => App.gDataContext.Cache.VPazVisit
                        .OrderByDescending(b => b.Cognome).ThenByDescending(b => b.Nome).ThenBy(b => b.Data)
                        .ToList());
                    break;
                case "AsceAlph":
                    aList = await Task.Run(() => App.gDataContext.Cache.VPazVisit
                        .OrderBy(b => b.Cognome).ThenBy(b => b.Nome).ThenBy(b => b.Data)
                        .ToList());
                    break;
            }
            try
            {
                foreach (var item in aList)
                {
                    MTreeViewPaz aMTree = new MTreeViewPaz(item);
                    Patients.Add(aMTree);
                }
            }
            catch (Exception e)
            {
            }
            treeView.Visibility = Visibility.Visible;
            return;
        }

This function is called the first time in OnNavigatedTo:

       protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            await LoadTreeAsync();
        }

It runs in less than a second. I have a 4 AppBarButtons to select the sorting state. In their method:

  private async void AppBarToggleButton_Checked(object sender, RoutedEventArgs e)
        {
            string sorting = await ApplicationData.Current.LocalSettings.ReadAsync<string>("TreeViewSort");

            switch (((Windows.UI.Xaml.Controls.AppBarToggleButton)sender).Name)
            {
                case "DescDate":
                    if (sorting == "DescDate")
                    {
                        return;
                    }
                    AsceDate.IsChecked = false;
                    AsceAlph.IsChecked = false;
                    DescAlph.IsChecked = false;
                    break;
                case "AsceDate":
                    if (sorting == "AsceDate")
                    {
                        return;
                    }
                    DescDate.IsChecked = false;
                    AsceAlph.IsChecked = false;
                    DescAlph.IsChecked = false;
                    break;
                case "DescAlph":
                    if (sorting == "DescAlph")
                    {
                        return;
                    }
                    AsceDate.IsChecked = false;
                    DescDate.IsChecked = false;
                    AsceAlph.IsChecked = false;
                    break;
                case "AsceAlph":
                    if (sorting == "AsceAlph")
                    {
                        return;
                    }
                    AsceDate.IsChecked = false;
                    DescDate.IsChecked = false;
                    DescAlph.IsChecked = false;
                    break;
                default:
                    break;
            }
            await ApplicationData.Current.LocalSettings.SaveAsync("TreeViewSort", ((Windows.UI.Xaml.Controls.AppBarToggleButton)sender).Name);
            _sorting = ((Windows.UI.Xaml.Controls.AppBarToggleButton)sender).Name;
            await LoadTreeAsync();
        }

It deadlocks he interface for more than 10 sec. I cannot understand why and how to solve it. I've checked and the queries are NOT impacting, they are executed in any case in few milliseconds.

I do not like this method a lot as it destroys and re creates all the oobjects. So I've even tried to change it so that if Patients is not null instead of destroying and re creating I use LINQ to sort the existing objects:

                    treeView.Visibility = Visibility.Collapsed;

                    _Patients= new ObservableCollection<MTreeViewPaz>(
                                                from i in Patients orderby i.Data descending, i.Cognome, i.Nome select i);
                    await treeView.Dispatcher.RunAsync( Windows.UI.Core.CoreDispatcherPriority.Normal ,()=>
                        {
                        Patients.Clear(); 
                        Patients = _Patients;
                    });
                    treeView.Visibility = Visibility.Visible;

And I have a deadlock around 1 sec on the Clear and a second deadlock of 10 sec or more on the Patients = _Patients;

What am I doing wrong? why this massive difference from the first call to all other ones?


回答1:


And I have a deadlock around 1 sec on the Clear and a second deadlock of 10 sec.

LoadTreeAsync method has no task retrun value. So, we have no need make Task return method, please replace Task with void. I found there are many UI interactions in LoadTreeAsync mthod, please make sure that call them in UI-thread with Dispatcher.

private async void LoadTreeAsync()
{
    List<VPazVisit> aList = new List<VPazVisit>();
    if (_sorting == "")
    {
        _sorting = await ApplicationData.Current.LocalSettings.ReadAsync<string>("TreeViewSort");
    }

    treeView.Visibility = Visibility.Collapsed;
    Patients.Clear();
    switch (_sorting)
    {
        default:
        case "DescDate":
            aList = await Task.Run(() => App.gDataContext.Cache.VPazVisit
                .OrderByDescending(b => b.Data).ThenBy(b => b.Cognome).ThenBy(b => b.Nome)
                .ToList());
            break;
        case "AsceDate":
            aList = await Task.Run(() => App.gDataContext.Cache.VPazVisit
                .OrderBy(b => b.Data).ThenBy(b => b.Cognome).ThenBy(b => b.Nome)
                .ToList());
            break;
        case "DescAlph":
            aList = await Task.Run(() => App.gDataContext.Cache.VPazVisit
                .OrderByDescending(b => b.Cognome).ThenByDescending(b => b.Nome).ThenBy(b => b.Data)
                .ToList());
            break;
        case "AsceAlph":
            aList = await Task.Run(() => App.gDataContext.Cache.VPazVisit
                .OrderBy(b => b.Cognome).ThenBy(b => b.Nome).ThenBy(b => b.Data)
                .ToList());
            break;
    }
    try
    {
        foreach (var item in aList)
        {
            MTreeViewPaz aMTree = new MTreeViewPaz(item);
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                Patients.Add(aMTree);
            });

        }
    }
    catch (Exception e)
    {
    }
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        treeView.Visibility = Visibility.Visible;
    });

}


来源:https://stackoverflow.com/questions/61328545/uwp-treeview-ui-deadlock-loading-time-from-less-than-1-sec-to-more-than-10-sec

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!