views:

104

answers:

2

I want to enumerate all loaded assemblies in an Asp.NET application, using AppDomain.CurrentDomain.GetAssemblies(). However, when checking the documentation for AppDomain, I find the following statement:

Thread Safety

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

Since GetAssemblies() is an instance method, I take this as I have to make take some kind of lock around that call, if not for anything else so to prevent anyone else from loading a new assembly into the domain while I'm enumerating the current ones. I would expect AppDomain to provide some kind of SyncRoot property, but it doesn't, and I have not found any information on the web about how to do.

How am I supposed to synchronize this call?

Edit

  1. I know that the lock statement is used to create a cooperative lock, this is exactly the reason that I want to lock the AppDomain in the same way everyone else does (or should do), rather than create my own lock that won't prevent code that's not mine from loading assemblies while I'm enumerating them.
  2. I know that locks that can be taken by anyone are usually a bad idea, but I also know that not taking a lock when performing unsafe operations is even worse.
  3. Both answers so far say that GetAssemblies() is, in fact, thread-safe. This makes sense to me, and I would really expect it to be the case, but how do you know it? Does anyone have a reference to support this claim? My google-fu has failed me and Reflector shows that this method is a thin wrapper around an internal native method.
+2  A: 

SyncRoot properties in general are a very bad idea. One reason why is it's possible for 2 independently developed libraries to unknowingly decide to lock against a shared SyncRoot property and quickly introduce deadlocks into the application. Locking is an operation that cannot easily be reliably shared between two independent components. The best strategy here is to develop your own lock which is used by your components to synchronize access.

In this case though calling GetAssemblies is safe to do from multiple threads so no locking is needed. The warning you see is a general statement added to every class in the BCL unless the author specifically designed the type for thread safety and removed the message.

JaredPar
How can I see that it's safe? It's not documented as safe for the method, and the AppDomain class is documented as not being thread safe. The Assembly class, OTOH, is documented as being thread-safe.
erikkallen
Btw the SyncRoot is not a bad idea. The bad idea is to have state that is so shared that you never know who is using it. However, when that happens, which is the case for the AppDomain (for a good reason), it is better to have a SyncRoot than to not have it, since not having a well-defined object to lock on makes it impossible for you to prevent race conditions.
erikkallen
+1  A: 

That is a standard disclaimer; you don't need to worry about it.
In general, as long as you (or another thread) do not modify the object, instance methods can be called from multiple threads.

Note that you should never lock on an AppDomain object.

SLaks
Additionally, you should never lock on anything you don't own. If you didn't make the AppDomain object, you should be wary of locking on it.
sixlettervariables
Where can I possibly see that it is a standard disclaimer and doesn't particularly concern this method? In contrast, in the documentation for the Assembly class you can read "This type is thread-safe". My problem is that I can not know whether someone else modifies the object, since another simultaneous request might (directly or indirectly) invoke Assembly.Load, which no doubt will modify the list of loaded assemblies.
erikkallen