Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / January 2007

Tip: Looking for answers? Try searching our database.

COM interop multithreading problem : Unable to cast COM object of type 'System.__ComObject' to interface

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
ziphnor@gmail.com - 12 Jan 2007 12:27 GMT
Hi,

I have a DirectShow filter which implements a COM interface called
IDVBSubtitle. It is defined like this on the C++ side (simplified
version used to debug of course, real interface has more methods :)

// C19647D5-A861-4845-97A6-EBD0A135D0BF
DEFINE_GUID(IID_IDVBSubtitle,
0xc19647d5, 0xa861, 0x4845, 0x97, 0xa6, 0xeb, 0xd0, 0xa1, 0x35, 0xd0,
0xbf);

DECLARE_INTERFACE_( IDVBSubtitle, IUnknown )
{
 STDMETHOD(Test)(int status) PURE;
};

On the C# side it looks like this:
 [Guid( ... ),
 InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
 public interface IDVBSubtitle
 {
   void Test(int status);
 }

When i create an instance of the filter in C# i can call test as much
as i like succesfully, but ONLY from within the same thread that
created it. If i try to call the Test method from any other thread i
get this:
Unable to cast COM object of type 'System.__ComObject' to interface
type 'MediaPortal.Player.IDVBSubtitle'. This operation failed because
the QueryInterface call on the COM component for the interface with IID
'{C19647D5-A861-4845-97A6-EBD0A135D0BF}' failed due to the following
error: No such interface supported (Exception from HRESULT: 0x80004002
(E_NOINTERFACE)).

Again, note that this ONLY occurs when the call is made from another
thread than the one that created the filter. I have tried both creating
a seperate C# thread to call Test, and had a callback from the COM
object call Test, both gave the above error.

Reading the thread referenced below lead me to believe this problem is
related to thread apartment states, but unfortunately didnt give me a
solution. I have tried creating the calling thread as both STA and MTA,
but it makes do difference. Could someone give me a hint here, been
stuck on this for a few days?

Reference:
http://groups.google.dk/group/microsoft.public.dotnet.languages.csharp/browse_th
read/thread/bf1617e0ddcf1d9c/144f5a7cf1ae8165?lnk=st&q=Unable+to+cast+COM+object
+of+type%2C+STA%2C+MTA&rnum=1&hl=da#144f5a7cf1ae8165

TDC - 12 Jan 2007 19:38 GMT
You definately cannot invoke the COM object from an MTA thread.
Ideally you want to just call methods from the STA thread that created
the object.  IIRC, you should be able to call from one STA thread to
another if you have a typelib registered which allows the cirrect
marshalling to happen.

ziph...@gmail.com wrote:
> Hi,
>
[quoted text clipped - 41 lines]
> but it makes do difference. Could someone give me a hint here, been
> stuck on this for a few days?
ziphnor@gmail.com - 13 Jan 2007 17:25 GMT
> You definately cannot invoke the COM object from an MTA thread.

Interesting that you should say that: I checked the Main method of the
application im working on (i didnt write that myself). It is tagged
with [STAThread], so i suppose all the threads its spawns are STA as
well. I tried changing it to MTAThread (which im not too fond of since
there is a comment saying another component is dependent on STAThread)
and all my problems went away! So it seems that i can indeed call it
from an MTA thread. As far as i understand its the apartment mode of
the thread that creates the COM object that decides the apartment mode,
so when it is created with an MTA thread and only accessed by MTA
threads it seems to work.

When i previously tried spawning a MTA thread to create it, the other
STA threads couldnt access the COM object.

> Ideally you want to just call methods from the STA thread that created
> the object.

That is sadly not possible(or at least not worth the bother), the COM
object in question is a DirectShow filter which will be accessed by the
graph thread and additionally my own thread. I get the abovementioned
error even if the COM object calls back to a managed method and tries
to call its own methods (ie it notifies my of a new subtitle, and i
call a method to get it, within the callback thread).

> IIRC, you should be able to call from one STA thread to
> another if you have a typelib registered which allows the cirrect
> marshalling to happen.

Do you know where more information can be found on this?
TDC - 14 Jan 2007 19:22 GMT
COM objects have to be specifically coded to support MTA and most do
not, so I assumed your problem was calling an STA-oly object from an
MTA thread.  When you register the object dll, it will show the
apratment type supported in the registry, but it seems like you've
already determined it supports MTA.

As an aside, there is nothing in the .NET SDK that states that threads
always spawn threads of the same type.  You should explicitly use the
thread type you need.

Finally, the best resource is a book entitled .NET and COM:  The
Complete Interoperability Guide.  It's easily over 800 pages, if that
gives an idea of it's depth of coverage.

Tom

> > You definately cannot invoke the COM object from an MTA thread.
>
[quoted text clipped - 27 lines]
>
> Do you know where more information can be found on this?
ziphnor@gmail.com - 21 Jan 2007 15:11 GMT
> When you register the object dll, it will show the
> apratment type supported in the registry, but it seems like you've
> already determined it supports MTA.

Where exactly? I looked under the CLSID in the registry, but it doesnt
seem to store such information. As far as i understand DirectShow
filters are supposed to be 'free' threaded objects btw.

> As an aside, there is nothing in the .NET SDK that states that threads
> always spawn threads of the same type.  You should explicitly use the
> thread type you need.

Sure, but even if i create an MTA thread and create the object there,
the other threads cannot access it, so there is some significance to
the main threads apartment model. I suppose it might be related to the
'Main STA'  concept described here:
http://www.idevresource.com/com/library/articles/aparts.asp#multiap

> Finally, the best resource is a book entitled .NET and COM:  The
> Complete Interoperability Guide.  It's easily over 800 pages, if that
> gives an idea of it's depth of coverage.

Okay thanks :)
TDC - 22 Jan 2007 13:47 GMT
> > When you register the object dll, it will show the
> > apratment type supported in the registry, but it seems like you've
[quoted text clipped - 3 lines]
> seem to store such information. As far as i understand DirectShow
> filters are supposed to be 'free' threaded objects btw.

Drill into InprocServer32\ThreadingModel.

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.