zoukankan      html  css  js  c++  java
  • 《Win32多线程程序设计》学习笔记 第17章 OLE ActiveX COM

    Apartment Model

    在该模型中,一个对象和一个特定的线程有关联,只有在该线程的context之中才能够调用该对象。 COM的“apartment”是一个对象产生,运作和毁灭的地方。当client要求一个指向interface的指针,它是从一个特定的线程(也就是apartment)中发出请求。这个client可能只在该apartment中使用该interface指针。当然也有可能产生一个interface指针给其他的apartment使用,这种情况你必须使用COM函数 CoMarshalInterThreadInterfaceInStream() 和CoGetInterfaceAndReleaseStream()。

    Apartment model的内部运作系使用消息队列 。COM为每个在apartment model中登记在案的线程产生一个不可见的窗口。而我们知道,一个窗口的消息只能被产生该窗口的线程处理。所以,使用消息队列可以自动强迫适当的线程处理对COM对象的调用。副作用是使用apartment model的线程必须有一个消息循环,否则调用COM对象时消息将不会被派送。

    Free-Threaded Model

    在这个模型中,对于out-of-proc COM server(是个exe而不是dll) 中的对象的调用动作,是由属于COM的线程发出。换句话说,即使你的程序只有一个线程,COM自己也有一缸子线程,用来调用你的COM对象。

    如果server是in-proc(也就是dll形式 ),那么调用通常直接来自client,送往server,其间没有COM的介入。

    在in-proc server和out-of-proc server之间,存在一个基本差异,那就是由谁产生线程。在in-proc server 中,线程的产生与否完全被client程序中的线程个数所控制。一旦in-proc server开始执行,其典型行为类似于一个正常的多线程dll与应用程序之间的互动。但在一个out-of-proc server中,线程是由COM产生的。

    free-Threaded不依赖使用W'indows消息,所以没有必要拥有一个消息循环。避过消息循环,可以使得对free-threaded对象的调用能够比apartment model对象的调用更显著的快速处理。付出的代价是应用程序必须负起保护对象的完全责任。确定对象受到保护非常重要。在apartmodel中,由于外界请求总是一个个被处理,所以同步化控制根本不需要。

    client程序也可以声明为free-threaded。一个free-threaded client可以完全地把一个interface 指针传递给另外一个线程,并且可以在任何时间对任何线程中的interface发出调用。这个意思是client可以对着同一个对象同时发出多个请求,也因此一个free client可能在同一个时间使用5个不同线程中的同一个interface指针。

     声明一个线程模型

     一个COM client或者server必须声明其所支持的线程模型。对于exe文件,每个即将使用COM的线程都必须在调用任何COM函数之前先调用CoInitialize或者CoInitializeEX。线程模型即在那个时候选定。

    CoInitialize内部调用CoInitializeEx,并制定线程模型为COINIT_APARTMENTTHREADED。如果使用复合文档(compound documents),你必须以OleInitialize将OlE初始化,而该函数内部会调用CoInitialize,如果使用复合文档,你就不能够在任何已经调用过OleInitialize的线程中使用free-threaded 对象。

    HRESULT CoInitialize(
      LPVOID pvReserved  
    //must NULL
    );

    HRESULT CoInitializeEx(
      
    void * pvReserved,
      DWORD dwCoInit   
    //COINIT enum中的一个栏位  COINIT_APARTMENTTHREADED and COINIT_MULTITHREADED flags cannot both be set. 
    );

    返回值:如果成功,传回S_OK,如果参数不合法,传回E_INVALIDARG.如果线程先前调用过CoInitializeEx,并且给予不同的dwCoInit   值,传回RPC_E_CHANGED_MODEL.

    Dll server的运作又不同了,他不是在启动时注册其线程模型,而是将模型种类存储在注册表中。在CLSID/InprocServer32项目之下,DLL放置一个键,名为ThreadingModel。

    混合模型

    一个应用程序在某些线程中使用apartment model而在另外一些线程中使用free-threaded model是可能的。所有被注册为free-threaded的线程被说是生活在他们自己的apartment中。因此会有一个free-threaded apartment和多个线程,以及一个或多个标准的apartment,每个有用单一线程。

     interoperability

     一个client和server声明为不同的线程模型也是可能的。

    如果client和server都是outofproc,那么COM就可以负责让2个人安全地沟通。如果free-threaded client调用一个apartment model server,那么COM就会将那些请求一个个排好,使server一次处理一个。如果一个apartment model client调用一个free-threaded sderver,那么server被允许正规地处理那些请求。

    如果server是in-proc,那么com还是可以负责让通讯的两边交互。但是付出额外的代价。server通常被设计为in-proc,为的是让client发出的请求能直接到达server端,不必透过Com的协助。如果一个free-threaded client尝试使用一个apartment model 的in -proc server,那么CoM必须介入,做法是把请求掉往main apartment(也就是第一个调用CoInitializeEx的线程) ,并将每个请求一次送到in -proc server手上。

  • 相关阅读:
    linux设备驱动学习笔记(1)
    linux 设备驱动程序中的一些关联性思考
    linux——(2)文件权限与目录配置
    linux——(1)初识linux
    设计模式-状态模式(State Pattern)
    设计模式-组合模式(Composite Pattern)
    设计模式-迭代器模式(Iterator Pattern)
    设计模式-模板方法模式(the Template Method Pattern)
    设计模式-外观模式(Facade Pattern)
    设计模式-适配器模式(Adapter Pattern)
  • 原文地址:https://www.cnblogs.com/kwliu/p/2195899.html
Copyright © 2011-2022 走看看