C#, WPF, Автоматически вызывают Диспетчера. Вызвать при необходимости?

У меня есть программа с картой Геопространства, встроенной в него. Обработка событий для карты обрабатывается на отдельном потоке для хранения карты быстро реагирующей (например, события, которые стреляют, когда карта нажата).

Проблема, которую я имею, состоит в том, когда карта запускает событие, моя программа должна обновить некоторые вещи в, он - gui, и также перезвоните в карту для обработки помещающих изображений на карте.

Я пытался перенести весь метод обработчика событий в это. Диспетчер. Вызовите, который откладывает меня на основном потоке UI. Это работает отлично для обновления моего GUI, но когда я перезваниваю в карту, я нахожусь все еще на потоке UI, который может вызвать некоторые проблемы в карте.

В основном, для создания этой работы, я оказываюсь перед необходимостью выполнять dispatcher.invoke каждый раз, когда я хочу изменить управление на своем gui. Существует ли способ, которым я могу автоматически сделать это, не перенося каждый вызов в dispatcher.invoke? Я надеюсь, что это все имеет смысл.

Вот некоторый пример кода для события, о котором я говорю..

    private void Map_OnMapClicked(object sender, MapClickedEventArgs e)
    {
        this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
        {
            // Do something to update my gui
        }));

        Map.DoSomethingInTheMap();

        this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
        {
            // Do something to update my gui
        }));


        //etc etc etc
    }
6
задан user113164 5 February 2010 в 22:51
поделиться

2 ответа

Если вам нужно сохранить каждую соответствующую операцию в ее собственном контексте синхронизации, это, к сожалению, лучший подход. Вам нужно будет вызывать с помощью Диспетчера всякий раз, когда вы обновляете свой графический интерфейс.

Вот несколько советов, как упростить эту задачу:

  1. Попробуйте пакетировать свои операции с графическим интерфейсом пользователя. В дополнение к меньшему количеству кода (за счет меньшего количества вызовов вызовов) вы получите лучшую производительность. Каждый вызов Dispatcher.Invoke несет в себе изрядные накладные расходы, поскольку он отправляет сообщение в очередь сообщений Dispatcher, которое необходимо обработать.

  2. Рассмотрите возможность использования Dispatcher.BeginInvoke, чтобы избежать блокировки, если вам действительно не нужно ждать.

  3. Если вы можете использовать параллельную библиотеку задач из .NET 4 (или обратный порт на 3.5sp1 в Rx Framework), вы можете подумать о переработке этого, чтобы использовать экземпляры задач, синхронизированные с потоком графического интерфейса . Создав TaskScheduler с помощью FromCurrentSynchronizationContext, вы можете запланировать выполнение задач в графическом интерфейсе проще, чем вызовы Dispatcher Invoke. Это также может дать вам некоторый контроль над пакетной обработкой, так как вы можете легко запланировать их и заблокировать / подождать по мере необходимости.

6
ответ дан 16 December 2019 в 21:39
поделиться

Вы можете использовать что-то вроде PostSharp или попытаться сжать обновления пользовательского интерфейса до одиночных вызовов методов, когда вы вызываете их один раз и делаете много. Или даже такой шаблон (это Winforms, но идея та же):

private void UpdateToolStripItemText(ToolStripItem toolStripItem, string text)
{
    if (InvokeRequired)
    {
        Invoke(new UpdateToolStripItemTextDelegate(UpdateToolStripItemText), new object[] { toolStripItem, text });
    }
    else
    {
        if (text != null)
        {
            toolStripItem.Text = text;
        }
    }
}
2
ответ дан 16 December 2019 в 21:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: