Greg said:
For example, with COM, an object is compiled and delivered as a native
binary. It must be registered on the target machine. Then when an app
is run and it uses the COM object, the COM object is loaded into a
thread of the application process at runtime (if I'm not mistaken).
The point of registration is that it is a mechanism to associate the
unique name of the COM class (the CLSID) with the server that will be
used to create it. In other words it's a bit like a replacement for
LoadLibrary/GetProcAddress, except you don't have to give the name of
the server when instantiating a COM object, you just give the name of
the class.
Threading is handled through apartments. Most objects will specify the
type of apartment that they require because this also describes their
behaviour to being accessed by multiple threads. Only code in an
apartment can call COM objects so that means that all threads that
access (or host) COM object must be in apartments.
An STA object has no thread synchronization in its code and therefore it
can only be accessed by the same thread, if any other thread accesses
the object then the method call will be serialised as a Windows message
and put in the message queue attached to the STA thread. Periodically
the message queue is pumped for messages, and so the STA thread will get
the message and run the method. If an STA object creates another STA
object then the two will run in the same apartment (and their code will
only be called by the same STA thread).
An MTA object has thread synchronization in its code (or has code that
doesn't care about threads). The process will always have a thread pool
of threads that will run in the MTA. If an MTA thread creates an MTA
object and calls the object then methods will be run on that thread. If
an STA object creates an MTA object and calls it then a thread pool
thread (MTA thread) is used to make the call, so that means that there
is a transition from the STA thread to the MTA thread, and this is
called marshalling. Similarly if an MTA object creates and calls an STA
object then a new STA thread is created and the STA object will be
called on that thread and the inter-apartment (ie inter-thread) calls
will involve marshalling.
There are some COM objects that don't care what apartment they run in
(Both apartment type) and so these are created in the apartment of their
creators (STA or MTA). Note that STA objects are bound to the single
thread - they will always be called on the same thread - however an STA
thread can have more than one object. An MTA object can be called on any
of the threads in the MTA, so it is not bound to a particular thread.
For a .NET object (call it object_dotnet) that is in a DLL, is the
object itself loaded and JIT'ed when a client app uses it or is it
built and JIT'ed with the client app at compile time when the main
app exe is created?
Unless you use ngen (the native image generator), the code is just in
time compiled on a method-by method basis, that is just before a method
is called for the first time JIT compilation occurs. The code is then
cached and used for subsequent calls to this method in this instance of
the process. JIT compilation has a security aspect too - if your code
uses link demands and it is ngen'ed, ngen will be repeated if the
security policy is changed.
Also, from what I understand, .NET objects are in
the same thread as the client unike a COM object which uses a
separate thread.
Any insight into the compile and run time differences between a COM
and a .NET appreciated.
COM components are instantiated through a request to the COM runtime,
which is a little like an object broker - the COM runtime uses the CLSID
you provide to locate the server, it then loads the server and accesses
the class factory, and finally it requests an instance of the class with
the CLSID. This is dynamic linking and binding - as I said earlier, it
is a 'safe' equivalent of LoadLibraryEx and then calling GetProcAddress.
With .NET the linking and binding is static - the compiler *requires*
the metadata of the object when it compiles your code and a static
'link' is put in the assembly which effectively says 'create an instance
of this specific class in this specific assembly'.
Richard