Многопоточный пользовательский интерфейс в WPF

  1. У меня есть два потока пользовательского интерфейса, один из которых является основным потоком, а другой — фоновым потоком, чей ApartmentState — STA. Каждый поток создает свое собственное окно, а в фоновом окне есть кнопка «Отмена».

  2. Основной поток имеет функцию, которая занята и требует довольно много времени для завершения. Я надеюсь, что после нажатия кнопки «Отмена» основной поток должен остановить отнимающую много времени функцию.

  3. Ниже приведен псевдокод в основном потоке:

    за(...) {

      //Option A: Application.DoEvents(); 
      //Option B: Dispatcher.Invoke to update UI in background thread
      if(cancel)    
        return;  //Stop the time-consuming function
      else     
        DoSomething;
    

    }

Странно то, что событие нажатия кнопки «Отмена» НЕ захватывается и не обрабатывается фоновым потоком. IMO, каждый поток имеет свою собственную очередь сообщений, и когда я нажимаю кнопку «Отмена», это сообщение должно быть поставлено в очередь и немедленно обработано фоновым потоком, но, согласно моему локальному тесту, это не так, фоновый поток никогда не обрабатывает событие нажатия кнопки...

Какие-нибудь мысли?

Кстати, я думаю, что есть два способа решить вышеуказанную проблему: один — использовать Application.DoEvents, а другой — использовать Dispatcher.Invoke. Но мне все еще любопытно, почему фоновый поток НЕ может сразу обработать сообщение. Заранее спасибо.


person buaaji    schedule 02.05.2013    source источник
comment
Application.DoEvents не существует в WPF... Как вы это реализовали?   -  person Reed Copsey    schedule 02.05.2013


Ответы (1)


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

Обычно у вас будет один поток пользовательского интерфейса, и вы просто переместите фактическую вычислительную работу в фоновый поток. Обновления пользовательского интерфейса будут направляться обратно в основной поток по мере необходимости. BackgroundWorker отлично подходит для этого во многих случаях.

Что касается отмены, обычно лучше всего с этим справиться, используя структуру кооперативной модели отмены. который построен вокруг CancellationTokenSource и CancellationToken. Они были разработаны с учетом использования в нескольких потоках и автоматически обрабатывают необходимые барьеры памяти.

person Reed Copsey    schedule 02.05.2013
comment
Спасибо Рид. Да, я понимаю, что иметь два потока пользовательского интерфейса плохо... Но почему событие нажатия кнопки не может быть обработано фоновым потоком и почему работает Application.DoEvents? - person buaaji; 02.05.2013