多次加载 Dll 以允许 .Net 中的多线程

发布于 2024-10-03 00:25:50 字数 313 浏览 4 评论 0原文

我的 .Net 程序使用 fortran Dll 来执行数学函数(Arpack,求解特征模)。我相信 Fortran 包含静态变量并且通常不是线程安全的。而且它非常复杂,可能需要付出很多努力才能使其线程安全。该 Dll 不是很大(700K),所以我只想多次加载它(比如 4 次,或者可能 8 次)以允许线程同时工作。有人知道我该怎么做吗?我听说 LoadLibrary 在多次调用时总是返回相同的句柄。因此,就目前情况而言,我唯一的解决方案是在磁盘上拥有 Dll 的多个副本(Arpack1.dll、Arpack2.dll 等)并根据需要加载它们。非常可怕。

有什么想法吗?

尤安

My .Net program uses a fortran Dll to perform a maths function (Arpack, solves eigen modes). I believe the fortran contains static varibles and generally isn't thread safe. Also it's very complicated and would probably take a lot of hard work to make it thread safe. The Dll isn't very large (700K) so I just want to load it many times (say 4, or maybe 8) to allow the threads to work concurrently. Anyone have any idea how I can do this? I hear that LoadLibrary will always return the same handle when called multiple times. So, as it stands my only solution is to have multiple copies of my Dll on disk (Arpack1.dll, Arpack2.dll etc) and load them as required. Pretty horrible.

Any ideas?

Euan

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

还不是爱你 2024-10-10 00:25:50

您发现的解决方法实际上是一个相当不错的解决方法。带有 LOAD_LIBRARY_AS_IMAGE_RESOURCE 选项的 LoadLibraryEx() 可能会起作用的可能性很小。该选项允许您多次加载它。但我严重怀疑这一点,DLL 几乎肯定依赖于通过 DllMain 初始化其运行时支持代码。

我没有听到你提到的一件事是必须使用 GetProcAddress() 的痛苦。确保你这样做,否则当你开始线程时你仍然会破坏全局变量。每个线程必须使用自己的地址。

The workaround you found is actually a pretty decent one. There might be small odds that LoadLibraryEx() with the LOAD_LIBRARY_AS_IMAGE_RESOURCE option will work. That option allows you to load it multiple times. I seriously doubt it though, the DLL almost certainly relies on getting its runtime support code initialized through DllMain.

One thing I didn't hear you mention is the pain of having to use GetProcAddress(). Make sure you do or you'll still stomp global variables when you start threading. Each thread must use its own address.

伊面 2024-10-10 00:25:50

加载DLL并不是创建线程的方式。
您的两个选择是使用 AppDomains 或完全独立的进程。

最简单的方法可能是简单地使用主/从安排,其中使用库的逻辑全部在从进程中完成。主设备根据需要启动尽可能多的“从设备”,然后收集返回值。

在“从机”中编写代码就好像它是单线程的一样,因为……确实如此。

使用主服务器中的 System.Diagnostics.Process.Start 来启动这些东西。


一般来说,复制 DLL 并加载所有副本并不是一种万无一失的方法。 DLL 本身可以访问操作系统资源,例如互斥体甚至锁定文件。这些人不会意识到副本应该是“单独的”。

如果您的库纯粹是一个计算库,并且您真的非常想要执行复制并加载副本的方法,则可以创建硬链接以避免复制实际的 DLL 文件。 (在 Win7 或 Vista 上创建fsutil 硬链接

Loading the DLL is not the way to create a thread.
Your two options are to use AppDomains or outright separate processes.

The easy way to do it might be to simply use a master/slave arrangement, where the logic that uses the library is all done in the slave process. The master kicks off as many "slaves" as it wants or needs, and then collects the return values.

Write the code in the "slave" as if it is single threaded, because... it is.

Use System.Diagnostics.Process.Start from the master, to launch these things.


In general, copying the DLL and loading all the copies is not a failsafe approach; the DLLs themselves may access OS resources like mutexes or even lockfiles. These won't be aware that the copies are supposed to be "separate".

If your library is purely a compute library and you REALLY REALLY want to do the copy-and-load-the-copies approach, you can create hardlinks to avoid having to duplicate the actual DLL file. (fsutil hardlink create on Win7 or Vista)

风和你 2024-10-10 00:25:50

正如您所发现的,您不能多次加载该库。
我想你有两种可能性:

在这两种解决方案中,您都需要考虑进程/应用程序域之间的数据交换方法。无论如何,这都不是一个简单的任务!

As you figuered out, you cannot load the library multiple times.
I guess you have two possibilities:

In both solutions you need to consider a method of data exchange betwen the processes/app domains. Anyway, it won't be a simple task!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文