Если у вас нет опыта работы с многопоточностью, вам, вероятно, не следует начинать с TThread
, поскольку это всего лишь тонкий слой поверх нативной.Я считаю это также немного грубым по краям;со времени появления Delphi 2 он не претерпел значительных изменений, в основном он был изменен, чтобы обеспечить совместимость с Linux во временном интервале Kylix и исправить более очевидные дефекты (например, исправление сломанного класса MREW и, наконец, устаревшие Suspend()
и * 1003).* в последней версии Delphi).
Использование простого класса-обертки потоков также заставляет разработчика сосредоточиться на слишком низком уровне.Для правильного использования нескольких ядер ЦП лучше сосредоточиться на задачах, а не на потоках, поскольку разделение работы с потоками плохо адаптируется к меняющимся требованиям и средам - в зависимости от оборудования и другого программного обеспечения, работающего параллельно, оптимальное количествопотоки могут сильно различаться, даже в разное время в одной и той же системе.В этом отношении очень помогает библиотека, в которую вы передаете только куски работы и которая автоматически их распределяет для оптимального использования доступных ресурсов.
AsyncCalls - хороший первый шаг для введения потоков в приложение.Если в вашей программе есть несколько областей, в которых необходимо выполнить ряд длительных шагов, которые не зависят друг от друга, вы можете просто выполнить их асинхронно, передав каждую из них в AsyncCalls.Даже если у вас есть только одно такое трудоемкое действие, вы можете выполнить его асинхронно и просто отобразить пользовательский интерфейс выполнения в потоке VCL, опционально позволяя отменить действие.
AsyncCalls не очень хорош для фоновых рабочих, которыеоставаться в течение всего времени выполнения программы, и это может быть невозможно использовать, когда некоторые объекты в вашей программе имеют сродство к потоку (например, соединения с базой данных или объекты OLE, для которых может требоваться, чтобы все вызовы происходили в одном потоке).
Вам также необходимо знать, что эти асинхронные действия не типа «запусти и забудь».Каждая перегруженная функция AsyncCall()
возвращает указатель интерфейса IAsyncCall
, на который вам может потребоваться ссылка, если вы хотите избежать блокировки.Если вы не сохраните ссылку, то в тот момент, когда счетчик ссылок достигнет нуля, интерфейс будет освобожден, что заставит поток, освобождающий интерфейс, ждать завершения асинхронного вызова.Это то, что вы можете увидеть во время отладки, когда выход из метода, который создал IAsyncCall
, может занять таинственное время.
OTL, на мой взгляд, является наиболее универсальным из ваших трех вариантов, и я хотел быиспользуйте это без второй мысли.Он может делать все, что может TThread
, и AsyncCalls, а также многое другое.Он имеет продуманную конструкцию, которая является достаточно высокоуровневой, чтобы упростить жизнь пользователю и позволить порту в системе Unixy (при сохранении большей части интерфейса нетронутым) выглядеть по крайней мере возможным, если не простым.В последние месяцы он также начал приобретать некоторые высокоуровневые конструкции для параллельной работы. Настоятельно рекомендуется
OTL также имеет несколько десятков образцов, что важно для начала.AsyncCalls не имеет ничего, кроме нескольких строк в комментариях, но тогда его достаточно легко понять из-за его ограниченной функциональности (он делает только одно, но делает это хорошо).У TThread
есть только один образец, который на самом деле не изменился за 14 лет и в основном является примером того, как не нужно делать что-либо.
Какой бы вариант вы ни выбрали, ни одна библиотека не избавит от необходимости пониматьосновы потоковПрочитав хорошую книгу об этом, является необходимым условием для любого успешного кодирования.Например, для всех них требуется правильная блокировка.