Можно ли запустить (и остановить) поток внутри DLL? - PullRequest
4 голосов
/ 26 ноября 2011

Я размышляю над некоторыми идеями по созданию DLL для некоторых общих вещей, которые я делаю. Одна вещь, которую я хотел бы проверить, если это возможно, это запустить поток внутри DLL. Я уверен, что смог бы, по крайней мере, запустить его, и он автоматически освободится при завершении (и заставит его принудительно завершить себя) - что, как я вижу, не будет большой проблемой. Но как только я запускаю его, я не вижу, как я могу продолжать общаться с ним (особенно, чтобы остановить его), главным образом потому, что каждый вызов DLL уникален (насколько мне известно), но я также очень мало знаю о предмет.

Я видел, как в некоторых случаях DLL может быть загружена в начале и выпущена в конце, когда она больше не нужна. У меня 0 знаний или опыта работы с этим методом, кроме простого наблюдения за чем-то связанным с ним, я даже не могу сказать вам, что или как, я не помню. Но возможно ли это вообще?

Я знаю об ActiveX / COM, но это не то, что я хочу - я хотел бы просто базовую DLL, которую можно использовать в разных языках (особенно в C #).

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

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

РЕДАКТИРОВАТЬ: В конце я оберну DLL внутри компонента, поэтому при создании экземпляра компонента будет загружена DLL, и внутри DLL будет создан соответствующий поток, затем, когда компонент свободен, DLL выгружается. Также необходимо убедиться, что если есть, например, 2 из этих компонентов, то для каждого компонента будет загружено 2 экземпляра DLL.

Это как-то связано с использованием II интерфейса? Потому что у меня тоже 0 опыта с этим.

Не нужно прямо отвечать на него примерами исходного кода - ссылка на хороший учебник была бы полезна.

Ответы [ 4 ]

7 голосов
/ 26 ноября 2011

Базовый шаблон, который вы ищете, выглядит следующим образом:

  1. EXE вызывает функцию в DLL.
  2. EXE передает параметры по мере необходимости.
  3. DLL выполняетработает, запускает поток, возвращает дескриптор.И под дескриптором я подразумеваю в свободном смысле работы, а не в смысле дескриптора Windows.
  4. EXE теперь может обмениваться данными с DLL, вызывая больше функций, передавая дескриптор.
  5. DLL может связыватьсяс EXE, например, с помощью обратных вызовов, если EXE предоставляет обратные вызовы.
  6. Когда приходит время остановиться, EXE вызывает функцию DLL, передавая дескриптор.На этом этапе DLL исправляется.

За дескриптором находится любое состояние, необходимое DLL для отслеживания между вызовами.С точки зрения EXE этот дескриптор непрозрачен.

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

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

Что касается потоковой части, то лучше использовать библиотеку потоков более высокого уровня, чем необработанные потоки.Библиотека, которую я бы порекомендовал, это Primož Gabrijelčič's OmniThreadLibrary .

Относительно вашего редактирования:

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

Когда вы загружаете DLL в процесс, есть толькокогда-либо один экземпляр этого.В частности, если вы намереваетесь использовать глобальные переменные, будет только один экземпляр каждой глобальной переменной, независимо от того, сколько раз вы вызываете LoadLibrary.

2 голосов
/ 26 ноября 2011

Я пытался опубликовать это как комментарий, но без символов: короткий ответ - да, это должно быть возможно.Разработка API-интерфейса таким образом, чтобы он синхронизировался и работал хорошо, - это уже другая история.Я обычно пользуюсь сетевым мылом TCP / IP для межплатформенного / языкового общения, но особенно в среде, где вы ищете асинхронные операции.Нетрудно разработать сервис, в котором есть вызовы «Пуск», «Стоп» и «isReady».

http://docwiki.embarcadero.com/VCL/en/Classes.TThread

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

Вот основы создания библиотеки DLL: http://delphi.about.com/od/windowsshellapi/a/dll_basics.htm

Ниже приведены основы ее использования.Я был вдали от Delphi в течение пары лет, иначе я бы сделал быстрый пример, у меня не было желания покупать копию для себя, но принципы одинаковы для всех языков.Существует множество учебников по Java / C # по многопоточности и дизайну интерфейса.

Вообще говоря, «простая» установка может быть:

Класс - Объект WorkToBeDone - логический isRunning - логический isReady - остановка процедуры;- процедура запуска (работы);- функция isReady (): boolean;

Ваш поток будет выполняться в цикле while структуры:

procedure start(work) //inside new thread
begin
  isRunning := true;
  isReady := false;

  while(isRunning)
    begin
      doIncrementalOperationOnWork();
      thread.yield;
    end;
  work := thread.getWork();
  isRunning := false;
  isReady := true;

end;

Это грубый эскиз, но идея заключается в том, что внешний вызывающий может проверитьпосмотрите, готов ли он, и вернитесь, когда он будетЯ не уверен, что вы делаете, но это «возможное» решение.Управлять им очень много, и, как утверждает Delphi: 16 потоков на процессор - это их «верхний» предел.Просто знайте об ограничениях.У других людей могут быть лучшие предложения, это просто абстрактный шаблон, который я использую для разгрузки работы на потоки, который кажется простым и понятным.

1 голос
/ 26 ноября 2011

Множество вопросов и дней веселого обучения.

Загрузка и выгрузка DLL не сложна, вы добавляете функцию с именем dllMain. Это специальный человек, который использует Windows, когда его просят загрузить и выгрузить библиотеки DLL. Подробнее здесь

О Delphi

Множество статей о Delphi и потоках и о том, как использовать интерфейсы в Delphi.

Когда вы получите более конкретные вопросы, я смогу помочь. Однако, как программист на Delphi и C #, я писал бы этот материал на C #, упаковывая его для Com и затем вызывая его из Delphi. Вы получите гораздо больше помощи, найдете больше учебных пособий, а языковая поддержка, особенно в сложных сценариях, намного лучше.

BackgroundWorker и пул потоков, не говоря уже о параллельных расширениях, делают потоки в .net увлекательными. В Delphi это просто больно.

0 голосов
/ 26 ноября 2011

Внутри ПРОЦЕССА существуют потоки.

Процесс запускает исполняемый код: либо код, встроенный в .exe, либо код, загруженный из внешнего .dll.

Процесс также можетзапускать код «удаленно» - код в отдельном процессе или даже на отдельной машине - с такими технологиями, как DCOM (Microsoft COM / ActiveX), WCF (Microsoft .Net), RMI (Java) или CORBA / IIOP (среди прочих).

Поскольку вы разместили на форуме Delphi, вам лучше всего изучить Delphi Prism:

http://edn.embarcadero.com/article/41598

Если вы застряли в старой версии Delphi 7Лучше всего просто придерживаться необработанных сокетов для связи с удаленными ПК.

...