Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.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
托管WPF和本机代码互操作。承载在ServicedComponent中的WPF_Wpf_Com Interop_Com+_Sta_Servicedcomponent - Fatal编程技术网

托管WPF和本机代码互操作。承载在ServicedComponent中的WPF

托管WPF和本机代码互操作。承载在ServicedComponent中的WPF,wpf,com-interop,com+,sta,servicedcomponent,Wpf,Com Interop,Com+,Sta,Servicedcomponent,我正在努力在ServicedComponent中托管WPF应用程序。我有一个WPF库,我需要从本机代码中使用它。为了实现这一目标,我创建了一个outproc COM+组件,将所有WPF调用放入其中,并从本机代码中调用该组件,如下所示: // Managed [ComVisible(true)] public class HpPcKeyboardSrv : ServicedComponent, ISrv { ... } // Native CComPtr<ISrv> spIS

我正在努力在ServicedComponent中托管WPF应用程序。我有一个WPF库,我需要从本机代码中使用它。为了实现这一目标,我创建了一个outproc COM+组件,将所有WPF调用放入其中,并从本机代码中调用该组件,如下所示:

// Managed
[ComVisible(true)]
public class HpPcKeyboardSrv : ServicedComponent, ISrv
{
    ...
}

// Native
CComPtr<ISrv> spISrv;
hr = spISrv.CoCreateInstance(__uuidof(MySrv), nullptr, CLSCTX_SERVER);
ATLVERIFY(SUCCEEDED(hr));

hr = spISrv->WPFCommand();
ATLVERIFY(SUCCEEDED(hr));
public void WPFCommand()
{
    if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
    {
        Thread thread = new Thread(() =>
        {
            System.Threading.ApartmentState aptState = Thread.CurrentThread.GetApartmentState();
            Debug.WriteLine("Spawned thread apartment: {0}", aptState); // <- Still MTA

            // !!! If _Window is the member of the class, the thread will be MTA
            // !!! otherwise STA
            _Window = new Window();

            System.Windows.Threading.Dispatcher.Run();
        });

        Debug.WriteLine("Thread apartment state1: {0}", thread.GetApartmentState());
        thread.SetApartmentState(ApartmentState.STA);     // <- even though set as STA
        Debug.WriteLine("Thread apartment state2: {0}", thread.GetApartmentState());

        thread.IsBackground = true;
        thread.Start();
        thread.Join();
    }
}
另一个选项是使用
Application.Current.Dispatcher
。这种方法的问题是,在这个调用
应用程序中。Current
为null,因此没有可用的调度程序

嗯。接下来要尝试的是在STA模型中生成一个威胁,如下所示:

// Managed
[ComVisible(true)]
public class HpPcKeyboardSrv : ServicedComponent, ISrv
{
    ...
}

// Native
CComPtr<ISrv> spISrv;
hr = spISrv.CoCreateInstance(__uuidof(MySrv), nullptr, CLSCTX_SERVER);
ATLVERIFY(SUCCEEDED(hr));

hr = spISrv->WPFCommand();
ATLVERIFY(SUCCEEDED(hr));
public void WPFCommand()
{
    if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
    {
        Thread thread = new Thread(() =>
        {
            System.Threading.ApartmentState aptState = Thread.CurrentThread.GetApartmentState();
            Debug.WriteLine("Spawned thread apartment: {0}", aptState); // <- Still MTA

            // !!! If _Window is the member of the class, the thread will be MTA
            // !!! otherwise STA
            _Window = new Window();

            System.Windows.Threading.Dispatcher.Run();
        });

        Debug.WriteLine("Thread apartment state1: {0}", thread.GetApartmentState());
        thread.SetApartmentState(ApartmentState.STA);     // <- even though set as STA
        Debug.WriteLine("Thread apartment state2: {0}", thread.GetApartmentState());

        thread.IsBackground = true;
        thread.Start();
        thread.Join();
    }
}
public void WPFCommand()
{
if(Thread.CurrentThread.GetApartmentState()!=ApartmentState.STA)
{
线程线程=新线程(()=>
{
System.Threading.ApartmentState aptState=Thread.CurrentThread.GetApartmentState();

WriteLine(“派生线程单元:{0}”,aptState);//我可能正处于解决方案的轨道上,或者完全偏离了轨道-

基本上,上述方法加载所有资源字典并创建WPF环境。请选中“在代码中管理资源字典集合并在元素级别合并它们”


因此,在此之后,您可以从WPFCommand调用您的windows,而不必担心STA\MTA。

最后一段代码对我来说很有用。如果您将其按原样放在控制台应用程序中,生成的线程分区确实是STA,它应该是STA。您确定它与您的程序中的代码完全相同吗?它完全相同。我得到了这也是我发现的。请参阅我的更新。如果_Window是类的一个成员,那么线程是MTA。不管怎样,如果它是局部变量,线程模型实际上更改为STA。似乎应该以其他方式分配_Window。请共享一个重制代码。此代码显示生成的线程是STA。@SimonMourier。感谢您的帮助您的示例,但它不是ServicedComponent。请参阅此处的代码-我现在可以复制。在进一步挖掘之前,至少有两种方法可以解决此问题:1)将RequiredServer类标记为Apartment,而不是默认注册值(这会导致默认线程为MTA而不是STA)或者2)删除ServicedComponent派生(但是您可以保留COM+服务器激活-首先为什么需要ServicedComponent)。