Пользовательский интерфейс зависает при массовом создании объектов, даже при использовании задачи - PullRequest
0 голосов
/ 02 мая 2018

У меня есть метод OnLoadShapeFilePolygonsCommand(), который считывает детали многоугольника (геометрии) из файла и создает некоторые объекты. Затем они загружаются в наблюдаемую коллекцию, которая связана с сеткой данных.

Пока все эти обработки я показываю индикатор выполнения. Просто добавил индикатор выполнения со свойством IsIndeterminate, установленным на true, и когда все данные загружены, я установил видимость индикатора выполнения на false.

Моя проблема в том, что при создании объектов многоугольника пользовательский интерфейс зависает (индикатор выполнения зависает).

Я что-то здесь не так делаю? Пожалуйста, помогите.

private async void OnLoadShapeFilePolygonsCommand()
{
    // ...
    // some code

    await Task.Factory.StartNew(() =>
    {
        List<Ploygon> collection = new List<Ploygon>();
        foreach (Graphic g in graphics)
        {
            collection.Add(new Ploygon(g,.. .. ..);
        }
        return collection;
    },CancellationToken.None, TaskCreationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext())
    .ContinueWith((antecedent) =>
    {
        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Normal, ThreadStart)delegate ()
        {
            // MapPolygons is observable collection binded to datagrid.
            MapPolygons.AddRange(antecedent.Result);
            //...
        });
        },scheduler);
    }
}

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

Вы используете эту перегрузку метода Task.Factory.StartNew, предоставляя TaskScheduler в качестве аргумента.

Вы получаете TaskScheduler, используя статический метод TaskScheduler.FromCurrentSynchronizationContext. Как вы можете прочитать в документации, этот метод возвращает TaskScheduler, связанный с текущим System.Threading.SynchronizationContext.

Поскольку вы вызываете метод Task.Factory.StartNew (и, следовательно, метод TaskScheduler.FromCurrentSynchronizationContext) в потоке пользовательского интерфейса, вы фактически используете поток пользовательского интерфейса TaskScheduler, чтобы поставить в очередь свою работу. Это объяснение вашего пользовательского интерфейса.

Одно замечание: TaskCreationOptions.AttachedToParent здесь бесполезен, поскольку вы указываете эту опцию для родительской задачи. Почему вообще используете эту опцию?

Вместо использования метода Task.Factory.StartNew используйте метод быстрого доступа Task.Run (конечно, если вы нацелены на .NET 4.5 или более позднюю версию).

В качестве альтернативы используйте TaskScheduler.Default вместо TaskScheduler.FromCurrentSynchronizationContext().

0 голосов
/ 02 мая 2018

Почему вы используете await с Task.Factory.StartNew и ContinueWith?

Попробуйте вместо этого:

var collection = await Task.Run(
    () => graphics.Select(g => new Ploygon(g,.. .. ..)).ToList());

// MapPolygons is observable collection binded to datagrid.
MapPolygons.AddRange(collection);
...
...