I'm writing an application that uses a COM library. I have a class library that wraps the calls to the COM library and adds some more functionality. Eventually this will run as a Windows Service. For now I test it using a Winforms test harness.
When the class library is created by the test harness everything seems to be working OK. The problems start when I try to run it as a service. It is created OK and even the first call to the COM is OK. The COM object then raises an event that I handle and in response to the result in the event I call another function in the COM library. The function is invoked successfully in the case when I run it from the test harness but when running as a Service an exception is thrown:
System.InvalidCastException occurred Message="Unable to cast COM object of type '' to interface type ''. This operation failed because the QueryInterface call on the COM component for the interface with IID '{350ADD2A-18CB-4D9C-BE28-48D53F14E6FB}' failed due to the following error: The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))."
I can see that there are threading issues. In the test harness case all this calls happen on the main thread and in the case of the Windows Service both the Service OnStart override and the COM event handler are on different threads. I've been trying different things without success. Any suggestions?
Some COM components must be accessed only by STA threads. If this is the case for yours, you can do your COM work in an STA thread like so:
RunInSTAThread( () => com_object.DoSomething() );
private static void RunInSTAThread(ThreadStart thread_start)
{
Exception threadEx = null;
ThreadStart wrapped_ts = () =>
{
try
{
thread_start();
}
catch (Exception ex)
{
MethodInfo preserveStackTrace =
typeof(Exception).GetMethod("InternalPreserveStackTrace",
BindingFlags.Instance | BindingFlags.NonPublic);
preserveStackTrace.Invoke(ex, null);
threadEx = ex;
}
};
Thread thread = new Thread(wrapped_ts);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
if (threadEx != null)
{
throw threadEx;
}
}
This may not be the best use of threads (a new thread for every call) for your situation, but it's a starting point.
Is the Win service running under the same user account as the Winforms application?
It's resolved now. I had to re-arrange the threads. Now the COM object and all the calls to it are on the same thread and there are no inter-threading problems. Still the question how to deal with it in the common case remains unclear.
i have just closed the project and opened it again and error resolved
User contributions licensed under CC BY-SA 3.0