技术开发 频道

.NET 组件中的线程辅助


::WaitForSingleobject(hThreadSTA,INFINITE);
::WaitForSingleobject (hThreadMTA,INFINITE);

return 0;

}


long WINAPI MySTAThreadFunction(long lParam)
{
::CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);

cout << "From .NET when called from the STA Worker Thread (Direct Access) : "
<< spHelloNET->GetThreadID() << endl;

IHelloDotNetPtr spHello = NULL;
HRESULT hr = CoGetInterfaceAndReleaseStream(g_pStream1,
__uuidof(IHelloDotNet),
(void **)&spHello);

if(S_OK == hr)
{
cout << "From .NET when called from the STA Worker Thread (Marshaled) : "
<< spHello->GetThreadID() << endl;
}

return 0;

}

long WINAPI MyMTAThreadFunction(long lParam)
{

// 让线程进入MTA
::CoInitializeEx(NULL,COINIT_MULTITHREADED);

cout << "From .NET when called from the MTA Worker Thread (Direct Access) : "
<< spHelloNET->GetThreadID() << endl;

IHelloDotNetPtr spHello = NULL;
HRESULT hr = CoGetInterfaceAndReleaseStream(g_pStream2,
__uuidof(IHelloDotNet),
(void **)&spHello);

if(S_OK == hr)
{
cout << "From .NET when called from the MTA Worker Thread (Marshaled) : "
<< spHello->GetThreadID() << endl;
}

// 从线程退出
return 0;

}/* 结束MyMTAThreadFunction */
    当运行控制台应用程序时,这是得到的输出。
The Thread ID of the primary STA thread is : 2220 
From .NET when called from the primary STA Thread : 2220
The Thread ID of the STA based Worker thread is : 2292
The Thread ID of the MTA based Worker thread is : 2296
From .NET when called from the STA Worker Thread (Direct Access) : 2292
From .NET when called from the STA Worker Thread (Marshalled) : 2292
From .NET when called from the MTA Worker Thread (Direct Access) : 2296
From .NET when called from the MTA Worker Thread (Marshalled) : 2296
    注意:对于所有调用,在客户端中的线程呼叫之间,不会产生线程交换,在.NET组件中,也不会产生线程引发实际方法。还句话说,.NET组件是一个Context agile,总是在呼叫者线程里执行任务。从上面的代码片段中观察到:对象引用(例如:CoMarshalInterThreadInterfaceInStream/CoGetInterfaceAndReleaseStream)的封送拆收效果与在单元间传递直接对象引用的效果是一样的。最后,接受单元得到一个中立单元接口指针,此中立单元l接口指针能用来调用.NET组件。.NET组件展示Both 线程Classic COM 组件回忆的所有行为,而Both线程Classic COM 组件则集合the自由线程封送拆收器。

结论:.NET世界中COM组件的地位

    在这系列文章的第一部分:我们可以怎样把Classic COM 组件展示到在公共语言运行库 (通用语言执行层)范围内执行的.NET应用程序。通过使用前期绑定和晚期绑定,以及检查执行时类型和创建动态类型发现的方法,COM interop怎样无缝地允许你来调用你的COM组件。我们已经理解了在.NET 中,委托是怎样工作的,以及它们在.NET时间处理模式中所扮演的角色,以及作为适配器,COM Interop是怎样把classic COM中的连接点事件处理模式连接到.NET中的基于委托的事件处理模式。我们讨论了怎样把COM集合展示到.NET应用程序中,以及怎样使用C#'s foreach句法简单地通过集合元素来迭代。然后,我们研究了IDL文件中的方向属性是怎样被映射到C#中相应的方向参数类型。我们也学习了:通过使用继承和内含包容,Classic COM 组件可以利用的来自于.NET 应用程序的重用选项。最后知道当调用COM 组件时,托管线程是怎样宣告它们的单元辅助。

    在文章的后半部分,我们尝试探索来自于.NET时代以前的COM 感知客户端是怎样像classic COM 组件一样使用.NET 组件。从程序编辑方面来看,COM可调用的包装 以及通用语言执行层怎样无缝地推动产生此程序。我们简单地探索了使用属性将元数据发送到.NET类型的可能性,因此可以根据你的要求来修改被生成的类型库。我们也学习了两个世界中异常处理机制是怎样互相联系的。我们还讨论了怎样从处在非托管事件接受里的.NET 组件中接受异步事件通知。然后把注意力转向可以利用的安装选择,以及怎样把.NET 组件安装成共享程序集.最后讨论了.NET 组件里的中立线程行为,知道Context-agile .NET 组件如何与集合自由线程封送拆收器 (FTM)的线程Classic COM 'Both'组件相似。

    作为COM开发者可能想知道继续编写COM 组件,或者通过键入所有组件和商业逻辑代码(此商业逻辑代码是通过使用其中一种语言,例如:C#, VB.NET或者任何其它你所喜欢的生成通用语言执行层托管代码的语言包装成托管 组件),并且直接转移到.NET世界是非常有意义的。依我看来,如果有大量的COM代码,而不能一夜之间把这些COM代码转化成托管代码,综合利用interop的能力,重用来自于.NET应用程序的COM 组件。但是如果开始从空开始编写新商业逻辑代码,然后,最好的方法就是使用其中一种生成通用语言执行层 托管代码的语言,将代码包装成托管组件。通过这种方法,在托管和非托管边界之间传输时可以免受性能终结之苦。从程序设计方面来看,不管.NET应用程序正在访问一个Classic COM组件 还是访问一个托管组件,由.NET结构提供的工具以及由运行库提供的COM interop机制都能使它无缝。因此本质上,COM和勇敢的新用户.NET世界结合将非常幸福,我们所知道的、喜欢的COM仍然继续我们生活的精髓。
0
相关文章