Подтвердить что ты не робот

Каковы некоторые из основных принципов, необходимых для управления многопоточным использованием Delphi?

Я как бы новичок в программировании вообще (около 8 месяцев с включением и выключением в delphi и небольшим python здесь и там), и я нахожусь в процессе покупки некоторых книг.

Мне интересно узнать о параллельном программировании и создании многопоточных приложений с помощью Delphi. Всякий раз, когда я выполняю поиск "многопоточности delphi" или "delphi multithreading tutorial", я, кажется, получаю противоречивые результаты, поскольку некоторые из них касаются использования определенных библиотек (omnithread library) и других вещей, похоже, больше ориентированы на программистов с большим опытом.

Я изучил довольно много книг на delphi и, по большей части, они кажутся скользкими поверхностями и не углубляются по этому вопросу. У меня есть друг, который программист (он использует С++), который рекомендует, чтобы я узнал, что на самом деле происходит с базовой системой при использовании потоков, а не в том, как сначала реализовать их в моих программах.

На amazon.com есть довольно много книг о параллельном программировании, но ни один из них, похоже, не сделан с Delphi в виду.

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

Спасибо заранее.

4b9b3361

Ответ 1

Короткий ответ
Перейдите в OmnyThreadLibrary, чтобы установить его и прочитать все на сайте.

Более длинный ответ
Вы запросили некоторую информацию, вот так: Вот что нужно прочитать:

http://delphi.about.com/od/kbthread/Threading_in_Delphi.htm
Мне лично нравится: Многопоточность - путь Delphi.
(Он старый, но основы все еще применяются)

Основные принципы:
Ваше основное приложение VCL однопоточное.
VCL не был построен с многопоточным разумом, но поддержка нитей поддерживается болтами, так что большинство компонентов VCL являются потокобезопасными.
Способ, которым это делается, заключается в том, чтобы заставить CPU ждать, поэтому, если вы хотите, чтобы быстрое приложение было осторожным, когда и как общаться с VCL.

Общение с VCL
Ваша основная тема - детектив TThread со своими собственными членами.
Это переменные потока. Пока вы их используете, у вас нет никаких проблем.
Мой любимый способ общения с основным окном - использовать пользовательские окна "Сообщения" и postmessage для связи асинхронно.
Если вы хотите синхронизировать связь, вам нужно будет использовать метод критический раздел или synchonize.
См. Эту статью, например: http://edn.embarcadero.com/article/22411

Общение между потоками
Здесь все становится сложно, потому что вы можете столкнуться со сложными проблемами отладки синхронизации.
Мой совет: используйте OmnithreadLibrary, также см. Этот вопрос: Перекрестная связь в Delphi
Некоторые люди скажут вам, что чтение и запись целых чисел является атомарным на x86, но это не 100% истинно, поэтому не используйте их наивным образом, потому что вы, скорее всего, получите тонкие ошибки и в конечном итоге отладочный код.

Запуск и остановка потоков
В старых версиях Delphi использовались Thread.suspend и Thread.resume, однако они больше не рекомендуются и их следует избегать (в контексте синхронизации потоков).
См. Этот вопрос: С каким кодом Delphi следует заменить мои вызовы на устаревший метод TThread Suspend?
Также посмотрите на этот вопрос, хотя ответы более расплывчаты: TThread.resume устарел в Delphi-2010, что нужно использовать на месте?
Вы можете использовать suspend и resume для приостановки и перезапуска потоков, просто не используйте их для синхронизации потоков.

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

Давным-давно я написал приложение под названием Life32.
Его программа отображения для conways game of life. Это может генерировать шаблоны очень быстро (миллионы поколений в секунду на небольших шаблонах).
Он использовал отдельный поток для расчета и отдельный поток для отображения.
Отображение - очень медленная операция, которую не нужно делать каждое поколение.
Поток генерации включал в себя код отображения, который удаляет материал с экрана (когда он отображается), а поток отображения просто устанавливает логическое значение, которое сообщает потоку генерации также отображение добавленного материала.
Код генерации записывается непосредственно в видеопамяти с использованием DirectX, не требующих вызовов VCL или Windows, и никакой синхронизации не существует.
Если вы переместите главное окно, приложение будет продолжать отображаться в старом местоположении, пока вы не приостановите генерация, тем самым остановив поток генерации, после чего он безопасный обновит переменные потока.
Если потоки не синхронизированы на 100%, дисплей будет происходить слишком поздно, не так уж много. Он также имеет пользовательский менеджер памяти, который позволяет избежать потокобезопасной медлительности, что в стандартном диспетчере памяти. Избегая любых и всех форм синхронизации потоков, я смог устранить накладные расходы с 90% + (на небольших рисунках) до 0.

Ответ 2

Вы действительно не должны заставлять меня начинать с этого, но в любом случае мои предложения:

  • Не пытайтесь использовать следующее:

    • TThread.Synchronize
    • TThread.WaitFor
    • TThread.OnTerminate
    • TThread.Suspend
    • TThread.Resume (кроме конца конструкторов в некоторых версиях Delphi)
    • TApplication.ProcessMessages
  • Используйте API PostMessage для связи с основным потоком - разместите объекты в lParam, скажем.

  • Используйте очередь производителя-потребителя для связи со вторичными потоками (не очередь сообщений Windows - только один поток может ждать на WMQ, что делает невозможным объединение потоков).
  • Не пишите напрямую из одного потока в поля в другом - используйте передачу сообщений.
  • Постарайтесь очень тяжело создавать потоки при запуске приложения и полностью не закрывать их.
  • Использовать пулы объектов вместо постоянного создания и освобождения объектов для межпоточной связи.

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

Что Delphi должно было иметь встроенный:

  • TWinControl.PostObject(anObject:TObject) и TWinControl.OnObjectRx(anObject:TObject) - методы для публикации объектов из вторичного потока и запускать с ними событие основного потока. Тривиальная обертка PostMessage для замены плохой исполняющей, взаимоблокирующей, постоянно перезаписываемой TThread.Synchronize.

  • Простой, неограниченный класс производитель-потребитель, который действительно работает для нескольких производителей/потребителей. Это, как и 20 строк потомка TObjectQueue, но Borland/Embarcadero не смог справиться с этим. Если у вас есть пулы объектов, нет необходимости в сложных ограниченных очередях.

  • Простой класс потоковых, блокирующих, пулов объектов - опять же, очень простой с Delphi, поскольку он имеет переменные класса и виртуальные конструкторы, например. создание множества буферных объектов:
    myPool:=TobjectPool.create(1024,TmyBuffer);

Ответ 3

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

  • Примитивы синхронизации: мьютексы, семафоры, мониторы
  • Delphi реализации примитивов синхронизации: TCriticalSection, TMREWSync, TEvent
  • Атомные операции: некоторые знания о том, какие операции являются атомарными и что нет (обсуждается в этом вопросе)
  • Возможности многопоточности Windows API: InterlockedIncrement, InterlockedExchange,...
  • OmniThreadLibrary

Конечно, это далеко не полный. Я создал эту вики сообщества, чтобы каждый мог редактировать.

Ответ 4

Добавляя все остальные ответы, я настоятельно рекомендую прочитать книгу: "Современные операционные системы" или любой другой, входящий в детали многопоточности.

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