是否可以在DLL中启动(并停止)线程?

时间:2011-11-26 00:25:31

标签: delphi dll delphi-7

我正在考虑为我做的一些常见事情构建DLL的一些想法。有一件事我想检查是否有可能在DLL中运行一个线程。我确信我至少可以启动它,并在终止时自动释放它(并强制终止它自己) - 我可以看到这不会是一个大问题。但是一旦我开始它,我不知道如何继续与它通信(特别是为了阻止它)主要是因为每次调用DLL都是唯一的(据我的知识告诉我)但我也知道很少主题。

我已经看到在某些情况下,DLL可以在开始时加载,并在不再需要时在最后发布。我对这种方法有0个知识或经验,除了看到与之相关的东西,甚至不能告诉你什么或如何,我不记得了。但这有可能吗?

我知道ActiveX / COM,但这不是我想要的 - 我只想要一个可以跨语言使用的基本DLL(特别是C#)。

此外,如果有可能,那么我将如何从DLL到应用程序进行回调?例如,当我启动线程时,我很可能会将一个函数(在EXE中)分配为事件的处理程序(由DLL触发)。

所以我想我要问的是 - 如何加载DLL以进行连续工作并在完成时释放它 - 而不是根据需要调用DLL中的单个函数的简单方法。在相同的情况下 - 我可能会在DLL中分配变量或创建对象。我怎样才能确保一旦我分配了该变量(或创建对象),我怎样才能确保下次调用DLL时变量或对象仍然可用?显然,它需要一种初始化/最终化DLL的机制(I.E.在加载DLL时在DLL中创建对象,并在卸载DLL时释放对象)。

编辑:最后,我将DLL包装在组件内部,因此当创建组件的实例时,将加载DLL并在DLL内创建相应的线程,然后当组件被释放时,DLL被卸载。还需要确保如果有这些组件中的2个,那么将为每个组件加载2个DLL实例。

这与IInterface的使用有何关联?因为我也有0经验。

无需直接使用示例源代码回答 - 指向优秀教程的链接非常棒。

4 个答案:

答案 0 :(得分:7)

您正在寻找的基本模式如下:

  1. EXE调用DLL中的函数。
  2. EXE根据需要传递参数。
  3. DLL执行工作,启动线程,返回句柄。并且通过句柄我的意思是松散的工作意义,而不是意味着Windows句柄。
  4. EXE现在可以通过调用更多函数,传递句柄来进一步与DLL通信。
  5. DLL可以与EXE通信,例如通过回调,只要EXE提供了回调。
  6. 当需要停止时,EXE调用DLL函数,传递句柄。此时DLL整理了。
  7. 句柄后面是DLL需要跟踪调用之间的任何状态。从EXE的角度来看,这个句柄是不透明的。

    即使使用像C这样的非OOP语言,这种模式也可以正常工作。但是,使用OOP工具要容易得多。由于您希望跨越模块边界,因此使用接口而不是Delphi对象会更安全。如果跨模块边界传递Delphi对象,则只能传递对象的数据部分,而不能传递代码部分。

    使用接口时,DLL返回的接口变量将作为上面编号列表中的句柄。它包含任何实例数据。使用接口可以实现可扩展性。

    对于线程部分,最好使用更高级别的线程库而不是原始线程。我推荐的图书馆是PrimožGabrijelčič的OmniThreadLibrary

    关于你的编辑:

      

    我将DLL包装在一个组件中,所以当创建一个组件的实例时,将加载DLL并在DLL内部创建相应的线程,然后当组件被释放时,DLL就是卸载。还需要确保如果有这些组件中的2个,那么将为每个组件加载2个DLL实例。

    将DLL加载到进程中时,只有一个实例。特别是如果您打算使用全局变量,那么每个全局变量只有一个实例,而不管您调用LoadLibrary的次数。

答案 1 :(得分:2)

我试图将此作为评论发布,但用完了字符:简短的回答是肯定的,它应该是可能的。设计API以使其同步并且运行良好是另一个故事。我经常使用TCP / IP网络肥皂盒进行跨平台/语言通信,尤其是在您正在寻找异步操作的环境中。设计具有“开始”“停止”和“isReady”调用的服务并不困难。

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

你正在进入允许竞争条件并需要一些智能检查才能生效的领域。请注意这一点并阅读有关该主题的内容。

以下是创建DLL的基础知识: http://delphi.about.com/od/windowsshellapi/a/dll_basics.htm

这是使用一个的基础知识。我已经离开德尔福几年了,否则我会掀起一个简单的例子,我没有为自己购买副本的冲动,但所有语言的原则都是一样的。在线程和界面设计上有大量的Java / C#教程。

一般来说,“简单”设置可能是:

类    - Object WorkToBeDone    - boolean isRunning    - 布尔值isReady    - 程序停止;    - 程序开始(工作);    - function 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所说的那样,管理起来很多:每个CPU 16个线程是它们的“上限”。请注意这些限制。其他人可能有更好的建议,这只是我用来将工作卸载到线程上的一个抽象模式,看似简单直接。

答案 2 :(得分:1)

很多问题和充满乐趣的学习经历。

加载和卸载dll并不难,你添加了一个名为dllMain的函数。这是Windows在被要求加载和卸载dll时使用的特殊人员。更多细节在这里

About Delphi

关于delphi和线程的大量文章,以及如何在delphi中使用Interface。

当你得到一些更具体的问题时,我应该能够提供帮助。然而,作为Delphi和C#程序员,我会在C#中编写这些内容,将其包装为Com,然后从Delphi调用它。您将获得更多帮助,找到更多教程,特别是在复杂场景中的语言支持更好。

BackgroundWorker和线程池,更不用说并行扩展使.net中的线程变得有趣。在Delphi中,这很痛苦。

答案 3 :(得分:0)

线程存在于PROCESS内部。

进程运行可执行代码:内置于.exe的代码或从外部.dll加载的代码。

进程还可以“远程”运行代码 - 使用DCOM(Microsoft COM / ActiveX),WCF(Microsoft .Net),RMI(Java)或CORBA等技术在单独的进程中编写代码,甚至是单独的机器IIOP(以及其他)。

由于您在Delphi论坛上发帖,您最好的选择是调查Delphi Prism:

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

如果您遇到旧版本的Delphi 7,最好的办法就是坚持使用原始套接字与远程PC进行通信。