代码之家  ›  专栏  ›  技术社区  ›  Radoslav Hristov

服务在尝试调用COM库时引发异常[已关闭]

  •  -1
  • Radoslav Hristov  · 技术社区  · 17 年前

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

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

    System.InvalidCastException occurred Message=“无法转换COM 接口类型“”的“”类型的对象。此操作失败,因为 对COM组件的QueryInterface调用 IID{350ADD2A-18CB-4D9C-BE28-48D53F14E6FB}由于 以下错误:应用程序调用了 为另一个线程封送。(HRESULT的异常:0x8001010E (RPC_E_WRONG_THREAD))。“

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

    4 回复  |  直到 9 年前
        1
  •  1
  •   jlew    17 年前

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

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

        2
  •  0
  •   Igor Brejc    17 年前

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

        3
  •  0
  •   Radoslav Hristov    17 年前

    现在已经解决了。我不得不重新整理线。现在COM对象和所有对它的调用都在同一个线程上,没有线程间问题。 但在普通案件中如何处理这个问题仍然不清楚。

        4
  •  -1
  •   Sanjit Shedage    14 年前

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

    推荐文章