Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .Net COM对象需要是STA线程_C#_.net_Wpf_Multithreading_Com - Fatal编程技术网

C# .Net COM对象需要是STA线程

C# .Net COM对象需要是STA线程,c#,.net,wpf,multithreading,com,C#,.net,Wpf,Multithreading,Com,我正在为第三方系统实现一个.NET COM服务器,它是COM客户端(C++)。我提供了一个IDL,用于使用tlbimp生成.dll。在API中,它还建议实现双和单元接口。在这个COM服务器中,我必须实例化一个WPF组件,该组件当前失败,因为它必须从STA线程调用。我已经在谷歌上做了很多关于如何强制我的COM服务器成为线程模型公寓的研究。我更改了注册表项,但没有帮助,然后我发现了以下关于stackoverflow的文章: 我按照说明实现了ICustomQueryInterface,但失败了;这是我

我正在为第三方系统实现一个.NET COM服务器,它是COM客户端(C++)。我提供了一个IDL,用于使用tlbimp生成.dll。在API中,它还建议实现双和单元接口。在这个COM服务器中,我必须实例化一个WPF组件,该组件当前失败,因为它必须从STA线程调用。我已经在谷歌上做了很多关于如何强制我的COM服务器成为线程模型公寓的研究。我更改了注册表项,但没有帮助,然后我发现了以下关于stackoverflow的文章:

我按照说明实现了ICustomQueryInterface,但失败了;这是我的IDL:

[
    object,
    uuid(ABB09FED-F7BE-4654-88BC-5F4D2941111A),
    dual,
    nonextensible,
    helpstring("IDVRServer Interface"),
    pointer_default(unique)
]
interface IDVRServer : IDispatch{
    [id(1), helpstring("Creates a DVR Unit Connection based on connection information
    such as IP address, user name...")]
    HRESULT CreateConnection(
    [in] DVRConnectionInfo* pConnInfo, [out, retval] IDVRUnitConnection** ppConn);
};
这里是C#中的实现(包括ICustomQueryInterface):

Marshal.QueryInterface的结果始终为0x80004002 E_NOINTERFACE。我已经尝试了很多不同的东西,也来自StandardOleMarshalObject和ServicedComponent,但都没有成功。还有一个问题是,如果注册表真的算数,或者我可以忽略其中的ThreadingModel,我并没有从Noseratio的帖子中真正了解到这一点。提前感谢您对该主题的任何帮助


我使用的是VisualStudio 2012和.Net Framework 4。

嗯,不,这不是你的选择,你一直试图做的事情无法奏效。你在使用你的COM服务器的C++应用程序的支配下,它是创建线程的那个。如果它不想支持STA,那么您就有问题了。不管怎样,当您想要使用WPF时,这是一个问题,它的Application.Run()方法负责这一点非常重要。这些都是令人不快的系统集成细节,不容易被忽略。首先,和一个在C++应用程序上工作的程序员谈谈,看看什么是可能的。@ HANS,为什么不用正确的公寓创建一个第二线程并处理自己的问题?@ Voo我已经尝试过了,但是这不起作用,因为我需要在C++ GUI线程中有WPF组件。当我创建自己的STA线程时,这是不可能的。在这种情况下,你真的没有什么可以做的-你不能在事后更改线程的线程模型,而且你似乎不能使用其他线程。但是我是否理解@Noseratio正确,客户端使用的线程模型不重要,因为“如果通过COM封送到另一个线程,则无论创建者线程是否为STA,也不管其ThreadingModel注册表值如何,它们都会被封送到自己的线程中。”此外,API明确指出COM对象应为单元状态,因此我假设客户端也处于单元状态。
 [ComVisible(true)]
  [ClassInterface(ClassInterfaceType.AutoDual)
  public class DVRServer : IDVRServer, ICustomQueryInterface
  {
     private IntPtr _dvrPointer;
     public DVRServer() {
        NativeMethods.CoGetStdMarshalEx(this, NativeMethods.SMEXF_SERVER, out _dvrPointer);
      }

 public CustomQueryInterfaceResult GetInterface(ref Guid iid, out IntPtr ppv) {
      if (iid == NativeMethods.IID_IMarshal_DVRServerDispatch)
      {
         res = 0;
         res = Marshal.QueryInterface(_dvrPointer, ref NativeMethods.IID_IMarshal_DVRServerDispatch, out ppv);
         string hex = res.ToString("X");
         if (res != 0)
         {
            return CustomQueryInterfaceResult.Failed;
          }

          return CustomQueryInterfaceResult.Handled;
      }
     return CustomQueryInterfaceResult.Failed;
}
    static class NativeMethods
{

    public static Guid IID_IMarshal_DVRServerDispatch = new Guid("ABB09FED-F7BE-4654-88BC-5F4D2941111A");  
    public const UInt32 SMEXF_SERVER = 1;

    [DllImport("ole32.dll", PreserveSig = true)]
    public static extern void CoGetStdMarshalEx([MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, UInt32 smexflags, out IntPtr ppUnkInner);
}