Разделение GUI и логики в разных потоках в приложении Windows Form - PullRequest
1 голос
/ 26 августа 2009

В приложении Windows Forms я хочу отделить графический интерфейс от логики. Пользовательские запросы являются сложными и включают в себя связь, поэтому я не хочу, чтобы это зависело от потока GUI. Структура должна быть примерно такой:

        GUI -----> splash screen ---------> User Form --------------> ...
              |                        #
              | create Manager thread  | Show this Form
              #                        |
    Manager -----> Check user type -------> Wait for user command --> ...

Каковы ваши советы, рекомендации или шаблоны для такого дизайна? Это правильный выбор? Спасибо!

EDIT Поток диспетчера должен управлять графическим интерфейсом, а не наоборот. Более того, поток Менеджера должен жить в течение всего времени приложения.

Ответы [ 3 ]

4 голосов
/ 26 августа 2009

Традиционно такая работа выполняется с помощью BackgroundWorker

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

Результат похож на ваш шаблон, но для каждой задачи создается и уничтожается отдельный поток (ну, на самом деле, существует пул ...).

UI thread ---> Show splashscreen------------------->Show window-------
                      |                           |return to UI      |
                      | create background worker  |                  |
                      -> Process user ------------                   ->Perform query etc.

Хорошо, основываясь на вашем комментарии:

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

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

2 голосов
/ 26 августа 2009

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

У него есть события, которые будут очень полезны. DoWork и RunWorkerCompleted, которые очень пригодятся.

Вы также можете попробовать использовать Threads , они будут выглядеть примерно так: (Имейте в виду, что когда вы используете Threads, если вы хотите выполнить какую-либо работу с потоком пользовательского интерфейса, вы должны вызвать Invoke (), в противном случае вы получите исключение CrossThreadException)

private delegate void MyFunctionCaller();

//This will set up your worker thread and set it off
private void SetThreadToDoWork()
  {
  ThreadStart threadStart = new ThreadStart(DoWork);
  Thread MyThread = new Thread(threadStart);
  MyThread.Start();

  ShowSplashScreen();
  }

private void DoWork() 
  {
  DoMyWork();
  WorkCompleted();
  }

private void WorkCompleted()
{
if (InvokeRequired == true)
  {
  MyFunctionCaller InvokeCall = delegate { WorkCompleted(); };
  Invoke(InvokeCall);
  }
else
  {
  //Back to the UI thread now.
  }
}

ОП Редактировать

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

1 голос
/ 26 августа 2009

Я разработал похожий проект. GUI запускает менеджер в другом потоке. У менеджера есть какой-то метод получения команд из GUI. Графический интерфейс прослушивает события диспетчера, поэтому он обновляется только тогда, когда диспетчер вызывает событие. Чтобы избежать перекрестных потоков, я использовал методы «Invoke»

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