国产午夜成人免费看片无遮挡_日本免费xxxx色视频_免费人成网上在线观看_黄网址在线永久免费观看

當(dāng)前位置:雨林木風(fēng)下載站 > 技術(shù)開發(fā)教程 > 詳細(xì)頁面

用C++Builder創(chuàng)建多線程COM服務(wù)器

用C++Builder創(chuàng)建多線程COM服務(wù)器

更新時(shí)間:2022-04-28 文章作者:未知 信息來源:網(wǎng)絡(luò) 閱讀次數(shù):

Sunspot Lee

一、線程、Apartment和進(jìn)程

說道COM的線程模型,大家就會(huì)想到各種Apartment模型。但Apartment究竟是什么?如何建立一個(gè)Apartment呢?

Apartment就是線程的容器,線程中有關(guān)COM的操作必須在Apartment中進(jìn)行。Apartment分為STA和MTA兩種,STA是只能容納一個(gè)線程的容器,MTA是能容納多個(gè)線程的容器。COM規(guī)定,一個(gè)進(jìn)程中可以有多個(gè)STA,但最多只能有一個(gè)MTA。線程調(diào)用CoInitializeEx(NULL,COINIT_APARTMENTTHREADED)后,這個(gè)線程就建立并且進(jìn)入了一個(gè)STA,線程調(diào)用CoInitializeEx(NULL,COINIT_MULTITHREADED)后,這個(gè)線程就進(jìn)入了進(jìn)程公用MTA。一個(gè)線程不能同時(shí)進(jìn)入兩個(gè)Apartment。線程調(diào)用CoUninitialize()后,這個(gè)線程就退出了它所在的Apartment。設(shè)計(jì)COM對(duì)象時(shí)設(shè)定的“Apartment模型”就是指這個(gè)COM對(duì)象可以呆在那種Apartment中。一個(gè)線程建立的COM對(duì)象自動(dòng)地呆在這個(gè)線程所在的Apartment中。要是這個(gè)線程建立了很多個(gè)COM對(duì)象,那這些對(duì)象都呆在這個(gè)線程所在的Apartment中。

一個(gè)線程可以直接訪問它所在的Apartment中的COM對(duì)象,但要訪問另一個(gè)Apartment中的COM對(duì)象就必須經(jīng)過調(diào)度。因?yàn)镾TA中只有一個(gè)線程,別的線程要訪問這個(gè)線程建立的COM對(duì)象就必須讓這個(gè)線程代勞了,如此一來,對(duì)這個(gè)Apartment中所有的COM對(duì)象的訪問都是序列化的,這些COM對(duì)象就不用擔(dān)心有好幾個(gè)線程同時(shí)訪問它的麻煩事。MTA中的COM對(duì)象就沒這么舒服了,它們必須考慮到可能會(huì)有好幾個(gè)線程同時(shí)訪問它們。MTA之外的一個(gè)線程訪問MTA中的一個(gè)COM對(duì)象時(shí),系統(tǒng)會(huì)從COM系統(tǒng)線程池中取出一個(gè)線程進(jìn)入MTA,由它來代表客戶線程訪問這個(gè)COM對(duì)象。(COM系統(tǒng)線程池的機(jī)理是怎么樣的?池中有幾個(gè)線程?)



二、客戶與服務(wù)器

COM對(duì)象位于服務(wù)器中,服務(wù)器分為進(jìn)程內(nèi)服務(wù)器、進(jìn)程外服務(wù)器、遠(yuǎn)程服務(wù)器三種。進(jìn)程內(nèi)服務(wù)器是一個(gè)DLL文件,進(jìn)程外服務(wù)器是一個(gè)EXE文件,遠(yuǎn)程服務(wù)器是另一臺(tái)計(jì)算機(jī)上的一個(gè)DLL文件或EXE文件。遠(yuǎn)程服務(wù)器如果是一個(gè)DLL文件的話,由一個(gè)被稱為“Surrogate”的代理程序調(diào)用它。

進(jìn)程內(nèi)服務(wù)器中的COM對(duì)象的Apartment模型如果與客戶線程所在的Apartment相配合的話,客戶線程建立COM對(duì)象時(shí)會(huì)直接建立在客戶線程所在的Apartment中。比如Apartment模型與STA、Free模型與MTA,Both模型與STA或MTA。這樣客戶線程就可以直接調(diào)用COM對(duì)象而不用調(diào)度。否則就會(huì)專門建立一個(gè)線程,然后由這個(gè)線程建立COM對(duì)象,COM對(duì)象和客戶線程就分處在兩個(gè)Apartment中。進(jìn)程外服務(wù)器和遠(yuǎn)程服務(wù)器中的COM對(duì)象一定不會(huì)建立在客戶線程所在的Apartment中。對(duì)它們的調(diào)用一定要經(jīng)過調(diào)度的。



三、在C++Builder下建立一個(gè)多Apartment的進(jìn)程外服務(wù)器

由于不必考慮并行的問題,COM對(duì)象一般設(shè)成使用Apartment線程模型。進(jìn)程內(nèi)服務(wù)器還沒什么問題,如果你試著建了一個(gè)進(jìn)程外服務(wù)器,并且讓幾個(gè)客戶同時(shí)訪問服務(wù)器中的對(duì)象的話,就會(huì)發(fā)現(xiàn)這些訪問不是同時(shí)進(jìn)行的。如果有一個(gè)訪問特別費(fèi)時(shí)間,它后面的訪問就要等很久才能進(jìn)行。這是因?yàn)榉⻊?wù)器中只有一個(gè)STA,雖然每個(gè)線程都建立了自己的COM對(duì)象,但這些對(duì)象都在這個(gè)STA中,當(dāng)然無法并行執(zhí)行。

克服這個(gè)問題的辦法很簡單,打開Borland\CBuilder5\Include\Atl\Atlmod.h文件,把第266行的:

typedef TATLModule<CComModule> TComModule;

改成:

#ifdef __DLL__

typedef TATLModule<CComModule> TComModule;

#else

typedef TATLModule<CComAutoThreadModule<CComSimpleThreadAllocator> > TComModule;

#endif

再打開Borland\CBuilder5\Include\Atl\Atlcom.h文件,把第3214行的:

        DECLARE_CLASSFACTORY()

改成:

#ifdef __DLL__

        DECLARE_CLASSFACTORY()

#else

        DECLARE_CLASSFACTORY_AUTO_THREAD()

#endif

就可以了。重新編譯你的程序,同時(shí)開兩個(gè)客戶試一試,是不是并發(fā)執(zhí)行了?

先別高興得太早,如果你同時(shí)開了五個(gè)客戶,并且其中四個(gè)在執(zhí)行費(fèi)時(shí)的訪問,你就會(huì)發(fā)現(xiàn)第五個(gè)客戶的訪問要等待一段時(shí)間。這種現(xiàn)象與C++Builder的實(shí)現(xiàn)代碼有關(guān)。

作了前面的修改后,服務(wù)器啟動(dòng)后會(huì)預(yù)先生成幾個(gè)線程,這些線程各自進(jìn)入一個(gè)STA中。當(dāng)服務(wù)器接到客戶的訪問要求后,會(huì)循環(huán)指定一個(gè)線程負(fù)責(zé)這個(gè)客戶的建立COM對(duì)象、訪問COM對(duì)象的事務(wù)。

    比如第一個(gè)客戶要求建立一個(gè)COM對(duì)象,服務(wù)器就給一號(hào)線程發(fā)消息,讓這個(gè)線程建立一個(gè)COM對(duì)象并把這個(gè)COM對(duì)象的接口傳給客戶,以后第一個(gè)客戶對(duì)這個(gè)COM對(duì)象的訪問就全由一號(hào)線程代理。而第二個(gè)客戶的建立COM對(duì)象、訪問COM對(duì)象的事務(wù)就由服務(wù)器指定二號(hào)線程來辦,如果客戶太多,線程用完了,服務(wù)器又會(huì)讓一號(hào)線程負(fù)責(zé)客戶的要求,依次循環(huán)。如果客戶很多,線程可能會(huì)負(fù)責(zé)幾個(gè)客戶的訪問要求,而由同一個(gè)線程服務(wù)的客戶的訪問就會(huì)順序執(zhí)行。預(yù)先生成的線程數(shù)缺省為系統(tǒng)的CPU個(gè)數(shù)乘以四,也就是四個(gè)(除非你的機(jī)器有好幾個(gè)CPU)。

只能同時(shí)服務(wù)四個(gè)客戶當(dāng)然是不行的,讓我們繼續(xù)修改。打開主CPP文件,可以看到下面兩行代碼:

TComModule ProjectModule(0);

TComModule &_Module = ProjectModule;

改為:

TComModule ProjectModule(MyInitATLServer);

TComModule &_Module = ProjectModule;

其中“MyInitATLServer”是一個(gè)新加的函數(shù),定義如下:

void __fastcall MyInitATLServer()

{

  if (_Module.SaveInitProc)

    _Module.SaveInitProc();



  _Module.Init(ObjectMap, Sysinit::HInstance, NULL, 6);//注意這個(gè)6

  _Module.m_ThreadID = ::GetCurrentThreadId();

  _Module.m_bAutomationServer = true;

  _Module.DoFileAndObjectRegistration();

  AddTerminateProc(_Module.AutomationTerminateProc);

}

看到那個(gè)6沒有,這代表服務(wù)器啟動(dòng)后會(huì)預(yù)先生成6個(gè)線程,也就能同時(shí)服務(wù)6個(gè)客戶。這個(gè)6可以改成別的數(shù),當(dāng)然不要太大了,不然機(jī)器垮了可別怪我。

改到現(xiàn)在你可能比較滿意了,但其實(shí)這個(gè)服務(wù)器還是有缺陷:一開始就生成所有線程是不是太浪費(fèi)了?循環(huán)分配線程好象也不太合理,更重要的是,如果客戶程序中途垮了,沒有Release它建立的COM對(duì)象,那這個(gè)COM對(duì)象將一直存在下去,占用的資源無法收回。

要解決這些問題就比較麻煩了,建議大家看一看ATL源代碼,編寫自己的TComModule類和CComThreadAllocator類。



四、編寫多線程客戶程序時(shí)要注意的問題

建立客戶程序時(shí)必須包含的*_ATL.h文件中有一個(gè)很好的COM對(duì)象包裝類。比如我建立了一個(gè)ComLib服務(wù)器,里面有一個(gè)MyComObj對(duì)象,那么在ComLib_ATL.h文件中有一個(gè)TCOMIMyComObj類,它很好的封裝了MyComObj對(duì)象。寫單線程程序時(shí)可以這樣建立它:

TCOMIMyComObj aComObj = CoMyComObj::CreateInstance();

(CoMyComObj是定義在在ComLib_ATL.h文件中的一個(gè)輔助類)然后就可以使用aComObj了,不必調(diào)用CoInitializeEx()和CoUninitialize(),也不必釋放aComObj。假設(shè)MyComObj對(duì)象中定義了一個(gè)方法fun(),一個(gè)屬性num,可以這樣使用:

aComObj.fun();

aComObj.num = 14;

int val = aComObj.num;

注意到num的訪問方法了嗎?C++Builder靈活運(yùn)用了特有的__property關(guān)鍵字,不必調(diào)用get_num()和set_num()了。

如果在寫多線程客戶程序時(shí)也這樣就會(huì)出問題:除了第一個(gè)線程正常外,后面的的線程無法建立COM對(duì)象了。

問題出在CoMyComObj里面,它保證了會(huì)調(diào)用CoInitializeEx()和CoUninitialize()并且在整個(gè)進(jìn)程中只會(huì)調(diào)用一次。而在多線程客戶程序中,每個(gè)線程都必須調(diào)用CoInitializeEx()和CoUninitialize()一次。因此,除了第一個(gè)線程成功進(jìn)入了Apartment,別的線程都失敗了。

可以這樣建立TCOMIMyComObj對(duì)象:

    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

    IMyComObj *pComObj;

    OleCheck(CoCreateInstance(CLSID_MyComObj, NULL, CLSCTX_LOCAL_SERVER

      , IID_IMyComObj, (void **)(&pComObj)));

    TCOMIComObjInExe aComObj(pComObj);

……使用aComObj……

CoUninitialize();

注意,這段代碼必須寫在TThread::Execute()中,因?yàn)橹挥蠺Thread::Execute()里的代碼才是真正運(yùn)行在新線程中的。另外決不能調(diào)用pComObj->Release()。



后記

學(xué)COM的念頭起于看李維寫的那三本書中的第一本的時(shí)候,李維描述了建立多線程服務(wù)器的重要性,但具體方法只是一筆帶過。后來我看了Delphi帶的例子,想用在C++Builder中,卻無從下手。在關(guān)于COM的部分,Delphi和C++Builder相差太大了,而又沒有這方面的C++Builder的書,網(wǎng)上的資料也很少,只好自己摸索。期間曾在網(wǎng)上發(fā)貼提問,總是沒人回答,痛苦啊!

溫馨提示:喜歡本站的話,請收藏一下本站!

本類教程下載

系統(tǒng)下載排行

国产午夜成人免费看片无遮挡_日本免费xxxx色视频_免费人成网上在线观看_黄网址在线永久免费观看

  • <label id="pxtpz"><meter id="pxtpz"></meter></label>
      1. <span id="pxtpz"><optgroup id="pxtpz"></optgroup></span>

        精品av综合导航| 成人激情午夜影院| 国产精品1区2区3区| 欧美一区国产二区| 裸体健美xxxx欧美裸体表演| 666欧美在线视频| 美女脱光内衣内裤视频久久网站 | 色先锋aa成人| 1024亚洲合集| 91免费版在线| 五月婷婷激情综合网| 欧美成人艳星乳罩| 高清不卡一区二区在线| 中文字幕日韩一区二区| 欧美手机在线视频| 国产精品资源在线观看| 中文字幕一区二区三区视频| 在线一区二区观看| 久久av中文字幕片| 亚洲欧美日韩国产一区二区三区| 欧美精品一二三| 国产成人激情av| 亚洲综合色噜噜狠狠| 91精品国产综合久久精品| 国产精品一区二区三区乱码| 亚洲一区二区在线免费观看视频| 欧美电影免费观看高清完整版| 99国产精品久久久久久久久久 | 秋霞影院一区二区| 国产精品入口麻豆九色| 日韩欧美一级特黄在线播放| 91丨porny丨国产| 国产激情一区二区三区| 午夜一区二区三区在线观看| 国产精品久久久久精k8| 久久综合色综合88| 4hu四虎永久在线影院成人| 波多野结衣中文字幕一区二区三区| 日本不卡视频在线| 亚洲一区二区影院| 亚洲欧美中日韩| 久久久久久久久免费| 日韩欧美国产不卡| 欧美精品丝袜久久久中文字幕| 99v久久综合狠狠综合久久| 久久机这里只有精品| 一区二区三区在线免费视频| 日本一区二区电影| 日韩精品一区二区三区视频在线观看| 国产福利91精品| 亚洲小说欧美激情另类| 99国产精品久久久久久久久久| 婷婷开心久久网| 国产精品午夜在线观看| 欧美日韩在线三区| 99国产精品国产精品毛片| 国产成人啪免费观看软件| 亚洲午夜久久久| 一二三区精品视频| 国产欧美视频一区二区三区| 国产女主播一区| 精品美女一区二区| 欧美精品v日韩精品v韩国精品v| 精品视频全国免费看| 国产成人啪免费观看软件| 免费观看成人鲁鲁鲁鲁鲁视频| 国产精品传媒在线| 精品国产一区二区在线观看| 欧美日韩中文字幕精品| 91亚洲资源网| 国产成人精品综合在线观看 | 国产嫩草影院久久久久| 欧美日韩久久久一区| 日韩一区二区三区高清免费看看| 91网站黄www| 国产成人精品www牛牛影视| 久久激情五月激情| 蜜桃视频第一区免费观看| 亚洲h动漫在线| 亚洲一区二区五区| 亚洲自拍都市欧美小说| 久久影院视频免费| 日韩亚洲欧美中文三级| 91麻豆精品国产91久久久资源速度| 欧美无乱码久久久免费午夜一区 | 精品视频在线免费观看| 欧美三级资源在线| 欧美日韩一区中文字幕| 色999日韩国产欧美一区二区| aaa亚洲精品| 精品一区二区在线观看| 久久91精品久久久久久秒播| 日日夜夜一区二区| 成人三级伦理片| 色综合视频在线观看| 欧美午夜片在线看| 欧美一区三区四区| 制服丝袜国产精品| 91 com成人网| 欧美精品三级日韩久久| 热久久一区二区| 蜜桃精品视频在线观看| 国产高清无密码一区二区三区| 国产成人av在线影院| 91丨国产丨九色丨pron| 91福利视频久久久久| 7777精品伊人久久久大香线蕉的| 91精品国产综合久久久久久久久久| 欧美电影免费观看高清完整版| 欧美大片国产精品| 亚洲欧美日韩国产手机在线| 日韩在线a电影| 国产综合色在线| 日本精品一区二区三区高清 | 欧美成人国产一区二区| 国产亚洲精品aa午夜观看| 亚洲另类色综合网站| 亚洲国产精品一区二区久久| 自拍偷拍国产精品| 国产成人精品亚洲日本在线桃色| 91视频一区二区三区| 91精品麻豆日日躁夜夜躁| 国产区在线观看成人精品| 有坂深雪av一区二区精品| 久久69国产一区二区蜜臀| 94-欧美-setu| 亚洲日本在线a| 欧美国产日韩一二三区| 久久精品国产77777蜜臀| 亚洲欧美中日韩| 国产成人在线视频播放| 久久久www成人免费无遮挡大片| 亚洲国产欧美在线| 国产美女在线精品| 欧美一区二区三区日韩| 欧美成人猛片aaaaaaa| 老司机精品视频一区二区三区| www.爱久久.com| 久久综合色播五月| 日韩高清在线电影| 日本高清成人免费播放| 国产清纯美女被跳蛋高潮一区二区久久w | 国产日韩欧美精品一区| 午夜精品视频一区| 国产乱码精品一区二区三区忘忧草 | 26uuuu精品一区二区| 亚洲午夜影视影院在线观看| 成人自拍视频在线| 精品国产乱码久久久久久影片| 一二三区精品福利视频| 成年人午夜久久久| 国产欧美日韩精品a在线观看| 美女脱光内衣内裤视频久久网站| 国产精品一区二区三区网站| 国产精品福利一区| 国产成人精品综合在线观看| 久久久天堂av| 久久99国产精品久久| 日韩一区二区电影网| 日韩国产一二三区| 欧美一级高清大全免费观看| 日韩电影一区二区三区| 欧美一区二区私人影院日本| 午夜精品久久一牛影视| 欧美一区二区三级| 奇米888四色在线精品| 日韩视频免费直播| 极品少妇xxxx偷拍精品少妇| 337p粉嫩大胆色噜噜噜噜亚洲 | 亚洲图片自拍偷拍| 色先锋aa成人| 天天综合天天综合色| 欧美妇女性影城| 看电影不卡的网站| 久久久精品2019中文字幕之3| 97aⅴ精品视频一二三区| 亚洲乱码一区二区三区在线观看| 91视频免费播放| 日韩精品亚洲一区| 久久婷婷国产综合国色天香| 国产成人综合在线播放| 日本不卡视频一二三区| 久久亚洲综合av| 欧美日韩国产片| 国产高清不卡二三区| 免费观看一级欧美片| 国产亚洲一本大道中文在线| 成人av免费网站| 国产日韩欧美不卡在线| 欧美电影免费提供在线观看| 国产suv精品一区二区三区| 亚洲黄网站在线观看| 欧美哺乳videos| kk眼镜猥琐国模调教系列一区二区| 亚洲制服欧美中文字幕中文字幕| 91毛片在线观看| av不卡免费在线观看| 久久疯狂做爰流白浆xx| 亚洲免费观看高清完整版在线观看| 91麻豆精品国产|