我正在考虑为我做的一些常见事情构建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经验。
无需直接使用示例源代码回答 - 指向优秀教程的链接非常棒。
答案 0 :(得分: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时使用的特殊人员。更多细节在这里
关于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进行通信。