Cross-AppDomain call problems

K

Kai Iske

Hi,

I have seen a couple of threads dealing with similar questions, but I
haven't found one to answer my question, so here I go:

I have a service application that loads a couple of tasks (Plug-Ins you
might want to call them). When a task gets executed it will be executed
in its own AppDomain to allow

a) Easy unloading of DLLs
b) Version / Assembly independance to the controlling service

The service exposes a support object that implements a specific
interface. This object supports (for example) sending emails and relies
on a third party component for performing the SMTP tasks.

The interface reference to this object is passed to the tasks when
being executed (so we have one cross-appdomain call here). The tasks
perform their actions and might call back on the supplied interface
(cross-appdomain again).

However some tasks might require more improved email functionality. So
they link against that SMTP component themselves which might be
different to the version used by the service.

Problem is when one of these tasks actually calls back into the
supplied support object, the CLR comes back to me with a version /
assembly manifest mismatch exception. I would have thought that when I
return to the service AppDomain from my Task AppDomain I would be in
"safe land" as the object would be executed with any of its local
assemblies (no assembly is installed in the GAC), However to me it
seems that when the task calls back to the service, CLR attempts to
bind to the task's version of the SMTP component rather than the
service's component.

Is there any easy way I could get around this?

Thanks

Kai
 
D

David Levine

When you pass an assembly reference across appdomains it forces that
assembly (and possibly all the assemblies that it in turn references) to get
loaded in both appdomains. You have to break the chain of aseembly
references to avoid the problem you ran into.

The easiest way I've found to do this is by defining an inteface assembly
that itself has no external dependencies; give it a version number that
never changes. Put a copy of this assembly where both appdomains can access
it - duplicate copies are ok so long as they are both the same version
number. Create a remoted object that implements this interface in the other
appdomain and make calls on it. Make all calls to the other appdomain via
this interface and be careful to not pass any assembly references through
it.

For example, if you need to refer to a specific assembly on both sides then
pass a string of the assembly name or path as an argument and explicitly
load it on both sides.
 
K

Kai Iske

David,

thanks for your feedback, but actually this is exactly what I'm doing.
I have a simple interface assembly that defines all the types the two
appdomains need to being able to talk to each other without actually
knowing about each other.

One of the methods accepts an Exception instance though. It could be
that if there's an inner Exception in there that I'm passing assembly
references accross appdomains?!

Kai
 
D

David Levine

There must be something in one of the objects defined in the interface that
is causing the assembly to get loaded. An inner exception would not be it
unless it was a custom exception type defined in that assembly, and that
would only occur when the exception object was created with the inner custom
exception

I would look at all the arguments defined in the interface to ensure that
none of the types are leaking across the appdomain boundary.

If you could post a code snippet that duplicates the problem it would help.
 
K

Kai Iske

That's exactly it: It might be that I pass a custom exception accross
appdomains. I just checked my code again and in some cases could happen
that I pass custom assemblies accross. I have now changed it to only
pass the raw base types (Message, StackTrace etc.) accross using my own
wrapper.

Thanks for the help / hint

Kai
 
D

David Levine

Glad I could help


Kai Iske said:
That's exactly it: It might be that I pass a custom exception accross
appdomains. I just checked my code again and in some cases could happen
that I pass custom assemblies accross. I have now changed it to only
pass the raw base types (Message, StackTrace etc.) accross using my own
wrapper.

Thanks for the help / hint

Kai
 

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

Top