WPF, MVVM и асинхронная работа - PullRequest
4 голосов
/ 17 августа 2011

Я знаю, что этот вопрос задавался здесь раньше, но я прочитал несколько ответов, которые мне не помогли.

У меня есть ComboBox, который должен получить некоторую информацию, связанную с выбором избаза данных (вероятно, на потерянном фокусе, чтобы остановить тысячу звонков во время прокрутки).Эта информация предназначена только для отображения и не критична, поэтому получение фонового потока / задачи звучит как идеальное решение.Тем не менее, это занимает несколько секунд, так как он получает данные из некоторых очень больших таблиц.Пользователь может свободно переходить к другим задачам, поскольку эта информация действительно предназначена только для отображения / справки.

Этот вопрос требует использования фонового работника, но в этом решении есть две проблемы,1) Изменение выбора, когда работник уже работает, создает проблемы.Вы можете либо не запускать его во второй раз, то есть, когда он вернется, он больше не отображает действительную информацию для нового выбора, либо попытаться отменить его (что не всегда работает).2) По какой-то причине я не могу объяснить, что метод, который фактически обращается к базе данных для фонового работника, возвращается медленнее, если метод находится в Model, чем в ViewModel, где я не думаю, что он принадлежит.Я действительно не знаю, почему.

Этот вопрос имеет несколько голосов, но вопрос ОП сформулирован очень плохо, и выбранный ответ просто говорит: «Да, это должно сработать».

Метод этого вопроса выглядит многообещающе, но связанное видео длится час (я смотрел все это) и касается диспетчера только в течение 10-15 секунд, не объясняя его.Если у кого-то есть ссылка на статью, которая более подробно описывает этот метод, это было бы хорошо.

Пул потоков, как предложено здесь 1018 *, похоже, что это лучший путь, поскольку несколько запросов на поиск просто ставятся в очередь, а не вызывают уже запущенные ошибки.Тем не менее, в нем нет объяснения, как использовать пул потоков, вместо этого ссылки на статью MSDN.Если у кого-то есть ссылка на статью, которая более подробно описывает этот метод, это было бы идеально, так как это кажется лучшим решением (конечно, я могу ошибаться).

Я действительно пытался сделатьмои исследования по этому вопросу, но большинство из этих ответов просто говорят вам, какой метод использовать, а не как его использовать.Я действительно ищу "как".

Ответы [ 2 ]

6 голосов
/ 17 августа 2011

OK.Ваш вопрос:

  1. У вас есть элемент управления выбора со списком элементов
  2. У вас есть операция дорогая , которая возвращает некоторый результат из выбранного элемента (обратите внимание, что эта операция должна быть дорогой, а не просто требовать времени для возврата, чтобы вы не беспокоились о том, чтобы их не было слишком много одновременно) - поэтому вам нужно делать это параллельно
  3. На возвращенный результат не влияют, только отображаются - так что делайте это асинхронно
  4. Если текущий выбранный элемент изменяется, вам больше не нужен предыдущий результат - и предыдущие запросы должны быть отменены, как тольконасколько это возможно, потому что они дорогие

Что вы должны сделать с последними технологиями .NET:

  1. Использовать Reactive Extensions (Rx), установитевверх, так что он срабатывает только тогда, когда пользователь сохраняет текущий выбор, скажем, по крайней мере, 500 мс (вы не хотите создавать много многократно, когда пользователь продолжает нажимать внизклавиша со стрелкой)
  2. Когда дроссель сработает, вызовите метод async (Async CTP), который ожидает операцию в задаче (длительную, чтобы избежать голодания потокапул), а также положить в токен отмены;сохранить текущий выбор для сравнения позже
  3. Когда операция вернется, установите результат в свой контекст данных (к которому должен быть привязан ваш элемент управления отображением) - асинхронный метод всегда продолжается в потоке пользовательского интерфейса, поэтомуНе нужно беспокоиться о доступе к потоку
  4. Если дроссель сработает и имеется ожидающий токен задачи / отмены, сначала используйте токен отмены для отмены задачи, прежде чем создавать новую задачу согласно # 2.Ожидание сгенерируется, потому что Задача отменена, но это не имеет значения, поскольку она вам больше не нужна.
  5. Здесь нет проблем с параллелизмом, потому что Async CTP всегда продолжается в потоке пользовательского интерфейса.Что касается всех ваших операций, они все однопоточные и не будут наступать друг на друга.

Я думаю, что если вы используете Async CTP с Rx, это будет около 10 строккод.

Примечание. Если вы используете НЕ ДОРОГО , вам не нужно использовать токен отмены.Просто дайте заданию завершиться, но проигнорируйте результат.Тем не менее, рекомендуется все же отменить запрос к базе данных раньше, хотя это не дорого на клиентском компьютере, но дорого на сервере.

3 голосов
/ 17 августа 2011

Вы можете попробовать использовать асинхронную привязку:

<ComboBox Name="theCombo" ... />
<TextBlock Text="{Binding Path=SomeSlowProperty, ElementName=theCombo, IsAsync=True}" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...