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.
我的。net程序使用fortran Dll执行一个数学函数(Arpack,解决特征模式)。我认为fortran包含静态变量,并且通常不是线程安全的。而且它非常复杂,要保证线程安全可能需要大量的工作。Dll不是很大(700K),所以我只想多次加载它(比如4次或8次),以允许线程同时工作。有人知道我怎么做吗?我听说当多次调用LoadLibrary时会返回相同的句柄。因此,就目前而言,我唯一的解决方案是在磁盘上拥有多个Dll (Arpack1)。dll,Arpack2。并按要求加载它们。很可怕的。
Any ideas?
什么好主意吗?
Euan
尤安
3 个解决方案
#1
2
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.
你找到的解决办法其实很不错。使用LOAD_LIBRARY_AS_IMAGE_RESOURCE选项工作的可能性很小。该选项允许您多次加载它。但我严重怀疑,DLL几乎肯定依赖于通过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.
我没有听到您提到的一件事是不得不使用GetProcAddress()的痛苦。确保您这样做了,否则当您开始线程化时,您仍然会访问全局变量。每个线程必须使用自己的地址。
#2
2
Loading the DLL is not the way to create a thread. Your two options are to use AppDomains or outright separate processes.
加载DLL不是创建线程的方法。您的两个选项是使用appdomain或完全独立的进程。
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.
使用System.Diagnostics.Process。从大师开始,启动这些东西。
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".
通常,复制DLL并加载所有副本并不是一种故障安全方法;dll本身可以访问OS资源,如互斥体甚至锁文件。他们不会意识到副本应该是“分开的”。
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)
如果您的库纯粹是一个计算库,并且您确实希望执行复制-加载-复制方法,那么您可以创建硬链接,以避免重复实际的DLL文件。(fsutil hardlink create on Win7或Vista)
#3
0
As you figuered out, you cannot load the library multiple times. I guess you have two possibilities:
正如您所计算的,您不能多次加载库。我猜你有两种可能:
- Use multiple AppDomains: more informations
- 使用多个应用程序域:更多信息
- Use multiple processes to do the task: more informations
- 使用多个进程来完成任务:更多的信息
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!
在这两种解决方案中,都需要考虑在流程/应用程序域上进行数据交换的方法。无论如何,这不是一个简单的任务!
#1
2
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.
你找到的解决办法其实很不错。使用LOAD_LIBRARY_AS_IMAGE_RESOURCE选项工作的可能性很小。该选项允许您多次加载它。但我严重怀疑,DLL几乎肯定依赖于通过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.
我没有听到您提到的一件事是不得不使用GetProcAddress()的痛苦。确保您这样做了,否则当您开始线程化时,您仍然会访问全局变量。每个线程必须使用自己的地址。
#2
2
Loading the DLL is not the way to create a thread. Your two options are to use AppDomains or outright separate processes.
加载DLL不是创建线程的方法。您的两个选项是使用appdomain或完全独立的进程。
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.
使用System.Diagnostics.Process。从大师开始,启动这些东西。
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".
通常,复制DLL并加载所有副本并不是一种故障安全方法;dll本身可以访问OS资源,如互斥体甚至锁文件。他们不会意识到副本应该是“分开的”。
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)
如果您的库纯粹是一个计算库,并且您确实希望执行复制-加载-复制方法,那么您可以创建硬链接,以避免重复实际的DLL文件。(fsutil hardlink create on Win7或Vista)
#3
0
As you figuered out, you cannot load the library multiple times. I guess you have two possibilities:
正如您所计算的,您不能多次加载库。我猜你有两种可能:
- Use multiple AppDomains: more informations
- 使用多个应用程序域:更多信息
- Use multiple processes to do the task: more informations
- 使用多个进程来完成任务:更多的信息
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!
在这两种解决方案中,都需要考虑在流程/应用程序域上进行数据交换的方法。无论如何,这不是一个简单的任务!