Как программировать асинхронные приложения Windows Forms? - PullRequest
0 голосов
/ 05 октября 2009

Я пишу приложение Windows Forms на C #, которое выполняет много длительных процедур. Мне нужно запрограммировать приложение, чтобы графический интерфейс не блокировался. Как лучше всего это запрограммировать?

Я знаю, как использовать следующее:

  1. BeginInvoke / EndInvoke
  2. Повторный вызов Application.DoEvents() (вероятно, не очень хорошая идея)
  3. BackgroundWorker
  4. и т.д.

Но как управлять состоянием GUI с помощью обратных вызовов и т. Д. ... не тривиально. Есть ли решения для этого (в виде шаблонов или библиотек)?

Ответы [ 4 ]

2 голосов
/ 05 октября 2009

Использование BackgroundWorker - это самый простой способ сделать то, что вы пытаетесь сделать. BackgroundWorker упрощает логику работы с потоками, оставляя вам очень мало кода, который вам нужно написать. Вам просто нужно обработать три события (DoWork, ProgressChanged и RunWorkerCompleted) и следовать нескольким принципам:

  • Никогда не обновляйте интерфейс внутри вашего долгосрочного метода. Вместо этого вызовите ReportProgress и обработайте событие ProgressChanged в логике пользовательского интерфейса.
  • Поймите, что, поскольку рабочий не работает в потоке пользовательского интерфейса, исключение, которое выдает ваш метод, автоматически не отображается в пользовательском интерфейсе. Просто молча записывается на консоль. Когда метод завершен, очень важно проверить свойство Error RunWorkerCompletedEventArgs и обработать (или выдать) исключение. Если вы этого не сделаете, вы не узнаете, что ваш метод не удался.
  • Если метод можно отменить, убедитесь, что он периодически проверяет свойство CancellationPending, чтобы узнать, было ли запрошено аннулирование. Если это так, после завершения отмены установите свойство Cancel для объекта DoWorkEventArgs. Помните, что CancellationPending может быть истинным, а Cancel ложным; это происходит, например, когда пользователь запрашивает отмену, и метод завершает работу, прежде чем он сможет проверить CancellationPending.
  • Соответственно, отметьте Cancel в вашем обработчике RunWorkerCompleted, чтобы ваш пользовательский интерфейс мог обеспечить правильный ответ на то, что произошло во время работы работника.

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

1 голос
/ 05 октября 2009

Шаблон Model-View-Controller отделяет состояние вашего пользовательского интерфейса от визуальных аспектов пользовательского интерфейса. Пока ваша реализация MVC поддерживает потоки, она должна решать проблему управления состоянием для вас.

Вот как я работаю с многопоточными реализациями пользовательского интерфейса.

РЕДАКТИРОВАТЬ: Вот хороший пост о выборе реализации MVC для проектов WinForms.

0 голосов
/ 05 октября 2009

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

0 голосов
/ 05 октября 2009

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

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

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