Какое влияние имеет многопоточность на архитектуру настольного приложения? - PullRequest
7 голосов
/ 28 декабря 2010

Я пишу многопоточное настольное приложение.

В целом

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

Какую литературу вы рекомендуете восполнить этот пробел?

Особенно

Моя заявка состоит из

  • Presentation, который создает и управляет диалогами с помощью инструментария GUI,
  • Kernel, который знает все о домене приложения,
  • Controller, который знает Kernel и Presentation и умеренный между этими двумя.

Чтобы быть более точным, вот как файлы открываются:

  1. Presentation сигнализирует FileOpenCommand.
  2. ApplicationController получает этот сигнал и
    1. использует ApplicationKernel для создания File объекта,
    2. использует ApplicationPresentation для создания FilePresentation объекта,
    3. создает объект FileController, передавая File и FilePresentation конструктору.
  3. FileController регистрируется как наблюдатель на своих File и FilePresentation.

Допустим, File обеспечивает длительную операцию Init(), которая не должна блокировать пользовательский интерфейс. Мне пришло в голову два подхода:

  1. File::Init() возвращает объект, который инкапсулирует поток и может использоваться для регистрации наблюдателя, который уведомляется о прогрессе, ошибках, завершении и т. Д. Это накладывает большую ответственность на FileController (который будет наблюдателем) потому что теперь к нему обращаются как из основного потока, так и из рабочего потока.
  2. Полностью скрыть рабочий поток от Controller. File::Init() ничего не вернет, но ApplicationKernel будет сигнализировать о создании, прогрессе и ошибках длительных операций в главном потоке. Это затянет много общения через ApplicationKernel, превратив его в нечто вроде божественного объекта.

Какой из этих двух общих подходов к многопоточности в настольном приложении (если есть)? Какие альтернативные подходы вы рекомендуете?

1 Ответ

3 голосов
/ 28 декабря 2010

Я предлагаю вам рассмотреть модель актера .Это абстракция параллелизма, которая скрывает множество деталей, связанных с потоками, блокировками и т. Д.

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

Некоторые дополнительные комментарии, вызванные комментарием @ CMR ...

В модели актера я представляю, что приложение будет по-прежнему структурировано с использованием тех же компонентов, которые предложены в вопросе: Presentation, ApplicationController и т. Д. Разница с моделью актера заключается в том, что компоненты(сейчас актеры) не будут иметь прямых ссылок друг на друга.Скорее, они будут содержать каналы, на которые они могут публиковать асинхронные, неизменяемые сообщения друг другу.

Последовательность событий в случае «открыть файл» будет по существу такой же в модели актера, за исключением того, чтоканалы будут переданы в FileController на шаге 2.3 вместо прямых ссылок на объекты.Точно так же регистрация наблюдателя происходит по каналам.

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

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

Модель актера можно рассматривать как обобщение классического подхода «накачки событий» пользовательского интерфейса - за исключением того, чтокаждый компонент (субъект) одновременно запускает свой собственный насос событий, а не один насос, отправляющий кучу компонентов.Каркас Actor обеспечивает способ запуска большого или даже огромного количества таких «одновременных насосов» с очень низким уровнем накладных расходов.В частности, небольшое количество потоков (скажем, по одному на процессор) обслуживает большое количество действующих лиц.

...