尝试调用COM库时,服务会引发异常

时间:2009-04-22 16:25:33

标签: c# .net windows-services error-handling

我正在编写一个使用COM库的应用程序。我有一个类库,它包含对COM库的调用并添加了一些更多的功能。最终,它将作为Windows服务运行。现在我使用Winforms测试工具进行测试。

当测试工具创建类库时,一切似乎都正常。当我尝试将其作为服务运行时,问题就开始了。创建好了,甚至第一次调用COM都可以。然后,COM对象引发一个我处理的事件,并响应事件中的结果,我调用COM库中的另一个函数。当我从测试工具运行它时,该函数被成功调用,但当作为服务运行时抛出异常:

  

发生System.InvalidCastException Message =“无法转换COM   ''到接口类型''类型的对象。此操作失败,因为   用于接口的COM组件的QueryInterface调用   IID'{350ADD2A-18CB-4D9C-BE28-48D53F14E6FB}'由于   以下错误:应用程序调用了一个接口   为不同的线程编组。 (HRESULT的例外情况:0x8001010E   (RPC_E_WRONG_THREAD))“。

我可以看到存在线程问题。在测试工具的情况下,所有这些调用都发生在主线程上,而在Windows服务的情况下,Service OnStart覆盖和COM事件处理程序都在不同的线程上。我一直在努力尝试不同的事情。有什么建议吗?

4 个答案:

答案 0 :(得分:1)

某些COM组件只能由STA线程访问。如果是你的情况, 你可以像这样在STA线程中进行COM工作:

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;
            }
        }

对于您的情况,这可能不是线程的最佳使用(每次调用的新线程),但它是一个起点。

答案 1 :(得分:0)

Win服务是否在与Winforms应用程序相同的用户帐户下运行?

答案 2 :(得分:0)

现在已经解决了。我不得不重新安排线程。现在COM对象和它的所有调用都在同一个线程上,没有线程间的问题。 在常见情况下如何处理它的问题仍然不清楚。

答案 3 :(得分:-1)

我刚刚关闭了项目并再次打开它并解决了错误