UWP TreeView UI Deadlock - время загрузки от менее 1 сек c до более 10 сек c - первый запуск при новом запуске - PullRequest
0 голосов
/ 20 апреля 2020

У меня есть серьезная проблема с производительностью TreeView как с точки зрения времени загрузки, так и с точки зрения тупика пользовательского интерфейса.

        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;
        }

Эта функция вызывается впервые в OnNavigatedTo:

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

Работает менее чем за секунду. У меня есть 4 AppBarButtons, чтобы выбрать состояние сортировки. В их методе:

  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();
        }

Он блокирует интерфейс на более чем 10 се c. Я не могу понять, почему и как это решить. Я проверил, и запросы НЕ влияют, они выполняются в любом случае за несколько миллисекунд.

Мне не очень нравится этот метод, поскольку он разрушает и заново создает все объекты. Поэтому я даже попытался изменить его так, чтобы, если «Пациенты» не были нулевыми, вместо уничтожения и повторного создания, я использовал LINQ для сортировки существующих объектов:

                    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;

И у меня тупик около 1 se c на Клире и второй тупик 10 se c или больше на Patients = _Patients;

Что я делаю не так? почему это огромное отличие от первого звонка для всех остальных?

1 Ответ

0 голосов
/ 22 апреля 2020

И у меня есть тупик около 1 se c на клире и второй тупик 10 se c.

LoadTreeAsync метод не имеет значения повторного выполнения задачи. Таким образом, нам не нужно создавать метод возврата Task, замените Task на void. Я обнаружил, что в LoadTreeAsync mthod есть много взаимодействий с пользовательским интерфейсом, пожалуйста, убедитесь, что вызываете их в потоке пользовательского интерфейса с 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;
    });

}
...