Как дождаться завершения фонового потока / операции в коде пользовательского интерфейса WPF? - PullRequest
4 голосов
/ 13 января 2009

например. в Winforms я бы написал ...

// on UI Thread
    BackgroundWorker workerThread = new BackgroundWorker();
    workerThread.DoWork += new DoWorkEventHandler(LoadChildren);
    workerThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OnLoadChildrenCompleted);
    while (workerThread.IsBusy)
    {
      Application.DoEvents();
    }

В WPF, что эквивалентно Application.DoEvents в Winforms?

У меня есть свойство Children в моем классе ViewModel. HierarchicalDataTemplate настроен для чтения элементов из свойства Children.
TreeView отображает узлы. Когда пользователь расширяет узел, дочерние элементы узла генерируются из результатов этого свойства

public Node Children
{
  get
  {
    // 1. time-consuming LINQ query to load children from a SQL DB
    // 2. return results
  } 
}

Так что я хотел бы запустить 1. в фоновом потоке и дождаться его завершения, прежде чем возвращать результаты ... поддерживая отзывчивость интерфейса.

Поиск в Google привел меня к этой странице, которая использует DispatcherFrames для имитации вышеописанного метода . Но это, кажется, слишком много работы ... что намекает на «Я делаю это правильно?»

Ответы [ 3 ]

4 голосов
/ 13 января 2009

Насколько я понимаю, у вас есть такой поток:

  • Выполнить некоторые подготовительные работы (поток пользовательского интерфейса)
  • Выполнить некоторую фоновую работу (другой поток)
  • Выполнить некоторые отделочные работы (поток пользовательского интерфейса)

Вы хотите дождаться окончания второго маркера, прежде чем запускать код в третьем.

Самый простой способ сделать это - вызвать код второй пули обратно в поток пользовательского интерфейса (обычным способом), чтобы запустить третью пулю. Если вы действительно, действительно хотите использовать локальные переменные из метода, вы всегда можете использовать анонимный метод или лямбда-выражение для создания делегата для передачи фоновому работнику - но обычно было бы чище просто иметь метод "PostBackgroundWork" или что-то в этом роде.

РЕДАКТИРОВАТЬ: Это не было бы хорошо для свойства, как вы показали в отредактированном вопросе, но я бы реорганизовал это как запрос на получение дочерних элементов с обратным вызовом, когда он будет завершен. Это позволяет избежать всего беспорядка повторного входа и прояснить, что на самом деле происходит.

1 голос
/ 13 января 2009

В WPF, что эквивалентно Application.DoEvents в Winforms?

Нет встроенного, но вы можете легко написать свой собственный. Действительно, WPF дает вам больше возможностей для обработки сообщений, чем Winforms. См. Мой пост в блоге на Dispatcher Frames здесь . Он включает в себя пример, показывающий, как имитировать Application.DoEvents().

1 голос
/ 13 января 2009

Вызывать DoEvents в потоке пользовательского интерфейса в цикле, как это, не рекомендуется в WinForms или WPF.

Если ваше приложение не может продолжить работу, пока этот поток не завершит свою работу, то почему он находится в другом потоке?

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

Взгляните на контент сообщества на MSDN .

Это хорошая статья о DoEvents .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...