2011-11-26 59 views
4

我正在考虑一些构建DLL的一些常见的东西我做的想法。有一件事我想检查一下是否可能在DLL中运行一个线程。我确信我至少可以启动它,并在终止时自动释放它(并强制终止它的自我) - 我可以看到它不会有什么问题。但是一旦我启动它,我就不会看到如何继续与它沟通(特别是阻止它),主要是因为每次调用DLL都是唯一的(据我所知),但我也知道很少学科。是否可以启动(并停止)DLL中的线程?

我已经看到,在某些场合,一个DLL可以在开始装载,并在当不需要的话了年底发布。我对这种方法没有什么知识或经验,除了看到与之相关的东西外,甚至不能告诉你什么或怎样,我不记得。但这甚至可能吗?

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

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

所以我猜我问的是 - 如何加载连续工作一个DLL,并释放它,当我做完了 - 而不是根据需要调用DLL中的各个功能的简单方法。在相同的情况下 - 我可以在DLL中分配变量或创建对象。我如何确保一旦我分配了该变量(或创建对象),我如何确保在下次调用DLL时变量或对象仍然可用?显然,它需要一种机制来初始化/完成DLL(I.E.在加载DLL时创建DLL中的对象,并在卸载DLL时释放对象)。最后,我会将DLL包装到一个组件中,所以当组件的一个实例被创建时,DLL将被加载并在DLL中创建一个对应的线程,然后当组件被释放,DLL被卸载。还需要确保如果有这些组件的示例2,那么将为每个组件加载2个DLL实例。

这是以任何方式与使用IInterface有关吗?因为我也有这方面的经验。

无需直接与示例源代码回答吧 - 给一个很好的教程链接将是巨大的。

+0

在最后一个音符在那里,我的意思是,我不希望任何人花时间,并详细回答这个问题,我知道这是一个大课题,我需要的是有人向我展示了一个教程,做到这一点,没有使用ActiveX。 –

+2

启动线程,您无法通信和控制是一个坏主意。 –

+0

事实上,这就是为什么我想知道如何在他们开始后与他们沟通。 –

回答

7

你正在寻找的基本模式是这样的:

  1. EXE调用DLL中的函数。
  2. EXE根据需要传递参数。
  3. DLL执行工作,启动线程,返回一个句柄。我的意思是,在松散的工作意义上,而不是意味着Windows句柄。
  4. EXE现在可以通过调用更多的函数,传递句柄来进一步与DLL通信。
  5. DLL可以与EXE通信,例如通过回调,只要EXE提供了回调。
  6. 当停止的时候,EXE调用一个DLL函数,传递句柄。在这一点上,DLL收拾整理。

句柄的后面是DLL需要跟踪调用之间的任何状态。从EXE的角度来看,这个手柄是不透明的。

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

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

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

关于您的编辑:

我会换一个组件内的DLL,所以创建组件的实例时,DLL将被加载和相应的线程将DLL内创建,然后当组件被释放时,DLL被卸载。还需要确保如果有这些组件的示例2,那么将为每个组件加载2个DLL实例。

当您将DLL加载到进程中时,它只有一个实例。特别是如果你打算使用全局变量,每个全局变量只会有一个实例,无论你调用多少次LoadLibrary

+0

所以,为了确保我理解正确:如果我在DLL中声明了一个变量,并且我发送了一个调用到设置该变量的DLL,那么下次我调用DLL中的另一个函数时,该变量仍将被分配为最后一次调用的方式?我害怕尝试不知道肯定是有可能的。 –

+0

如果您使用全局变量,当然。但你不想这样做。至少因为你有线程。因此将状态存储在句柄或接口后面的对象中。 –

2

我试图张贴此作为一个评论,但跑出来的字符:简单的答案是肯定的,它应该是可能的。设计API使其同步且运行良好是另一回事。我通常进入TCP/IP网络soap框进行跨平台/语言交流,但特别是在您寻找异步操作的环境中。设计一个具有“开始”“停止”和“isReady”呼叫的服务并不难。

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

你潜入境内,将允许竞争条件,需要一些聪明的检查是有效的。请注意这一点并阅读相关主题。

这里的基础上建立一个DLL: http://delphi.about.com/od/windowsshellapi/a/dll_basics.htm

下面是使用一个基础。我已经离开德尔福一两年了,否则我会掀起一个快速的例子,我没有急于为自己购买副本,但所有语言的原则都是一样的。在线程和界面设计中,有很多Java/C#教程。

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

类 - 对象WorkToBeDone - 布尔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; 

其粗草图,但这个想法是外线来电可检查,看它是否已准备就绪,并返回时,它是。我不确定你在做什么,但这是一个“可能的”解决方案。正如德尔福所说的那样,管理很多东西:每个CPU有16个线程是它们的“上限”。请注意这些限制。其他人可能会有更好的建议,这只是一个抽象模式,我用它将工作转移到线程上,看起来简单而直接。

+0

一些很好的观点,但不是我正在寻找的答案,谢谢。 –

+2

每个cpu限制16个线程。你可以解释吗? –

+0

@DavidHeffernan,来自上面链接的文档(http://docwiki.embarcadero.com/VCL/en/Classes.TThread):'跟踪太多的线程会消耗CPU时间;建议的限制是单处理器系统上每个进程有16个活动线程。 –

0

线程存在于一个PROCESS内部。

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

的方法还可以运行代码“远程” - 在单独的过程码,或甚至一个独立的机 - 与像DCOM(微软的COM/ActiveX),WCF(微软.NET),RMI(爪哇)或CORBA技术/ IIOP(等等)。

既然你张贴在德尔福论坛,你最好的选择可能是调查德尔福棱镜:

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

如果你坚持使用旧版本的Delphi 7的,你最好的选择可能是只需坚持原始插座与远程PC进行通信即可。

+0

只是为了说明,因为我们彼此之间:我不认为我的例子是一个很好的设计选择,这是对这个问题的技术答案。 –

+0

与远程PC进行通信的问题在哪里出现?我在两个地方提到我不想故意使用ActiveX。而且我也不想离开Delphi7 - 我实际上是从Delphi 2010降级的。 –

+3

-1。这并没有回答所问的问题,没有提到任何关于“与远程PC通信”的问题,也没有在Delphi论坛(这是StackOverflow)中被问及,与使用Prism而不是Delphi无关。问题是关于Delphi DLL中的线程。 –

1

很多问题和有趣的日子打包学习经验。

加载和卸载dll并不难,您添加一个名为dllMain的函数。当被要求加载和卸载dll时,它是Windows使用的特殊人员。更多详细的关于Delphi和线程,以及如何使用接口在delphi文章

About Delphi

充足。

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

BackgroundWorker和线程池,更不用说并行扩展使得.net乐趣线程化。在德尔福,这只是痛苦的。

+0

这看起来很有希望,看着它... –

+0

在德尔福有线程的人有plentty。在C#中有很多很好的线程库,使用interop对我来说听起来不是一个好主意。 –

+0

也对我有用,但是如果我有选择使用c#或Delphi的线程,我知道我会选择哪一个。 –