Trace across AppDomains



If this is simple, forgive my ignorance, but I'm coming from the
CompactFramework where we don't use AppDomains. I did a fair bit of archive
searching and couldn't find an answer and I got no responsed in the remoting
group after a week, so I'm throwing a little wider net this time.

I have a desktop app (FFx 2.0) developed with Studio 05 that loads
assemblies in a separate AppDomains from the primary UI. I'd like to be
able to hook up a TraceListener in the UI AppDomain and then get information
to it from Trace.Write in the other AppDomains.

I realize that the Trace data exists inside the individual AppDomains, but
Studio itself seems to have no problem receiving and displaying the Trace
statements from all AppDomains that I'm running, so I know that doing this
is possible.

Is there some general practice or pattern that would allow me to get the
Trace info from all AppDomains (within my actual process is fine)?


Chris Tacke, Embedded MVP
OpenNETCF Consulting
Giving back to the embedded community


I get the distinct impression from reading your post that there is a
misunderstanding of what AppDomain really means here. When you say something
like "loads assemblies in a separate AppDomains from the primary UI", can you
be specific about what this means? How are you accessing classes and methods
in these assemblies that are in "separate AppDomains"?
If you truly have Trace data happening in a separate AppDomain, you would
need to have a mechanism that implements MarshalByRefObject (like Remoting)
semantics to marshal the data back to the other AppDomain for display. There
are a couple of other statements in your post such as "within my actual
process is fine" that further indicate there may be some confusion.

"Inside every large program, there is a small program trying to get out."


Sorry I wasn't clear - the app is pretty complex, but I'm fairly sure
(though not 100%) that I'm not confused about what's going on.

We have a main application that runs the UI for a large pluggable framework.
Basically it's a development environment that dynamically loads up other
assemblies. These assemblies are each hosted in a separate AppDomain and
called through a remoted interface. The methods are called via Reflection
through that remoted interface using MethodInfo and PropertyInfo pulled from
the assembly's types at load.

There's nothing that inherently makes these assemblies have to be on the
local PC - they just currently are (we're designing so they don't
necessarily have to be). We also may have some interaction with other
processes on the same machine in the future.

So if I load up the UI, and it in turn loads up an assembly through remoting
in another AppDomain, if I call Trace.Writeline the trace statements show up
in Studio. However a TraceListener on the "UI App" doesn't see it. A
TraceListener in the spawned AppDomain does, and the TraceListener in the UI
sees Traces from it's own domain - all as expected.

What I'm wondering is how exactly is Studio getting these Traces from all
AppDomains currently running under the debugged process. Is there some
standarized way to do it? Since as far as I can tell I can't remote events,
and I certainly don't want to poll all loaded assemblies across every
AppDomain we spawn (there's one per assembly and there can be a lot of
assemblies), is there a reasonably efficient mechanism to do it?


- Chris

Nicholas Paldino [.NET/C# MVP]


There are two issues here, IMO.

The first I think, depends on the underlying store for the class that
derives from TraceListener. If the store is something that handles
concurrency well (like say, the Event log, or SQL Server) then you shouldn't
have to worry.

However, if it is something where you need to worry about concurrent
access to the underlying source, then you need to make sure that access to
that underlying store is synchronized.

This is important even if you are using the trace in the same app
domain. Of course, this is assumed, since the trace methods can be called
from any thread in the app domain.

The second issue here is the TraceListener itself. All TraceListeners
derive from MarshalByRefObject. Because of that, when creating your new
AppDomains, pass the TraceListener to your app domain and then add it to the
TraceListeners in the new app domain. This way, when the methods on the
Trace class are called in the new app domain, it will access the underlying
store in the original app domain. Since the TraceListener derives from
MarshalByRefObject, all calls made to the trace listener from the new app
domain will be marshaled to the orignal app domain.

This can, of course, have a performance impact if this is moved across

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