Sharing DLL between threads

R

Ram P. Dash

Hi:

I've a third party DLL (not a .NET class library PE) which I use using
DllImport attribute in my application running in multiple threads invoking
different methods of the same DLL.

The memory usage of the application is shooting to 1GB in just 30 minutes.
It goes till it's 1.4GB after which I get OutOfMEmory exceptions. If I don't
use the DLL, my memory stays put at 100MB.

I tried freeing the DLL using FreeLibrary but after few seconds I am getting
"Object reference not set to an instance of an object" while accessing the
methods of the DLL.

How can I ensure that only one copy of the DLL per thread is in my
application memory and that the DLL is unloaded when it's no longer used by
any of the threads?

BTW, my application is an ASP.NET web service but this has nothing to do
with the statelessness of a webmethod because I am spawning and running the
threads in the background at application level.

Thanks,
Ram
 
L

Lloyd Dupont

if you use standart PInvokde mechanism: DON'T EVER FREE your LIBRARY
amd it can't be unloaded.
but don't wory, there is, already, one single instance of the DLL in memory
for all thread (of all process!!!)

if you memory goes that up, it's very likely to be a bug in your application

DLL used with standart mechanism won't upload and DON'T EVER call a function
in a FREED Library.
That will crash your program instantly or, worst, cause weird, mysterious,
alien bugs...


On the other hand, with .NET 2.0 you could transform IntPtr (of a function
pointer) to a delegate.
So you could used LoadLibrary/FreeLibrary & GetProcAddress.
But even then, NEVER call into a FREED library.
 
R

Ram P. Dash

Thanks,

However when I looked at the ProcessModuleCollection somewhere in my code, I
saw the same DLL appear three times in the collection my test environment
(where close to 5 threads run at a time). Doesn't that tell that three
copies of the same DLL is in my application memory?

Thanks,
Ram
 
R

Ram P. Dash

Now this is a classic. The impersonation fails for CASE I but doesn't fail
for CASE II.

Case I:

Client Side Code
-----------------
System.Net.NetworkCredential credential = new
System.Net.NetworkCredential("myUserName", "myPassword", "myDomain");
ServiceA a = new ServiceA();
a.Credentials = credential;
a.SomeMethod();

Server Side Code
------------------
Web.config
-----------
<authentication mode="Windows" />
<identity impersonate="true" />

ServiceA
---------
[WebMethod]
public void SomeMethod() {

// Write to share drive code (the share drive has myUserName in ACL
list, myUserName should be able to write to it)
// But it fails
}

Case II:
Everything being same if I change only the Web.config as follows, it works:

<authentication mode="Windows" />
<identity impersonate="true" userName="myDomain\myUserName"
password="myPassword" />

I've tried the following for CASE I as suggested in
http://support.microsoft.com/default.aspx?scid=KB;en-us;q306158. But nothing
works.

a) Changing the "userName" attribute from "machine" to "system" in
"processModel" node in machine.config
b) Including ASPNET user in following Group Policy:
\Local Computer Policy\Computer Configuration\Windows Settings\Local
Policies\User Rights Assignment\"Act as part of the operating system"

Infrastructure: Windows XP Pro (Service Pack 1); .NET Frmaework 1.0 (No
service pack)

Our corporate policy strongly favors doing things as in CASE I. How can I
make it work?

Thanks,
Ram
 
W

Willy Denoyette [MVP]

Case I can only work in a WK2 AD realm with Kerberos delegation set-up
correctly.
However, I'm not entirely clear on your infrastructure, you said Windows XP
SP1, does it mean the client and the webserver and the File server are all
the same machine or are all different machines running XP?
Another remark is that you should apply the SP for the framework, or do you
like the tons of bugs present in v1.0.

Willy.
Note as this is another topic, you should start another thread.
 
L

Lloyd Dupont

mmh... you makes me wonder.
I haven't used this window much so I'm not sure, but do you have an address
for the DLL, I'll bet, it's the same address everytime.

Theoritically DLL are loaded once and there is a system wide counter
incremented every time they are used and decremented evrytime they are
freed.
normally, all what a process could do is increment this counter.

it's one of the major concept of the DLL, so I kind of doubt XP bug on
this....
 
Z

Ziga Jakhel

1) What sort of a dll is this? If a C++ or similar, are you sure it releases
it's memory properly after use?
I had such a problem a while ago... forgot to clean up the c++ dll from my
C# interop wrapper. When you describe your memory leaks, this is the type of
problem I would put my money on.

2) I'm not entirely sure you can freely multithread anything you may want
to. Are you sure the component is thread safe and that the results you're
getting back are ok?

3) In general you could wrap your dll into a managed wrapper that runs as an
EnterpriseServices (COM+) server.
This way it runs out-of process of the main application, you can pool the
objects, and you get object lifetime & recycling control (you can set the
memory limits; e.g. if the mem usage of the object reaches xx megs, kill it,
and use a freshly instantiated object with next call; or put a number of
calls limit on it - the object gets recycled every xx calls).

This is the way to go when you have rogue unmanaged third-party dlls that
don't work quite properly. Sure, you lose some performance, but gain a lot
of stability.
Win Xp or w2k3 are recommended, though, as they use COM+ 1.5 which offers
more features.

Regards,

Sigmund Jakhel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top