2013-04-17 154 views
0

在註冊(RegAsm)我的C#COM可見類後,我發現CoCreateInstance(__uuidof(myclass))僅第一次需要很多時間,同一客戶端進程中的後續嘗試會立即得到解決。任何想法爲什麼需要時間? NGen不適合我。CoCreateInstance需要很多時間

我的COM服務器是在C#和客戶端是在MFC/ATL

CComPtr<namespace::Imyclass> obj; 
hrx = obj.CoCreateInstance(__uuidof(namespace::myclass)); 
+0

您的COM客戶端寫什麼語言/環境? –

+0

「第二次」是什麼意思?第二次在同一個客戶端進程中調用CoCreateInstance?或者第二次啓動客戶端應用程序時,速度會更快? – selbie

+0

@selbie在同一客戶端進程中發送時間,如果我重新啓動我的客戶端,它又會有明顯的延遲 –

回答

0

CoCreateInstance第一通電話可能有諮詢註冊表和文件系統,加載相應的代碼,允許其初始化,最後調用一個工廠來創建你要求的實例(如果它可能位於)。

第二個調用從前面的這些步驟中獲益匪淺。如果第一次調用成功,那麼代碼已經被加載和初始化,並且只需要第二次調用工廠。

1

第一次調用CoCreateInstance必須加載進程並初始化.NET運行時。然後,你的DLL必須被加載,「驗證」並編譯成機器代碼(儘管及時幫助加快啓動速度)。 .NET運行時還必須解析程序集的元數據,然後動態生成並編譯「COM可調用包裝器」(http://msdn.microsoft.com/en-us/library/f07c8z1c.aspx),它們是非託管COM世界和託管.NET運行時之間的橋接代理。您的代碼可能使用的任何其他庫也需要加載,驗證並可能編譯爲機器代碼(如果不是NGEN'd)。

這本質上是一個昂貴的過程。你提到的延誤並不是聞所未聞的。

我不認爲你可以做很多事來加快速度。我建議你在啓動後不久創建一個對象,以考慮是否可以在程序生命週期的早期階段實現命中。它不會讓它變得更快,但它可能會顯着改善用戶體驗。如果你的程序不能容忍延遲,那麼你不應該使用.NET來編寫COM對象(更具體地說,你不應該在你的進程中使用.NET,這不是使用COM的問題;它是一個加載.NET的問題)

順便說一句,這是爲什麼在.NET中編寫外殼擴展是「非常灰心」的原因之一。關於這個問題,請看最近的帖子,這也涉及.NET的啓動性能:http://blogs.msdn.com/b/oldnewthing/archive/2013/02/22/10396079.aspx

(這就是爲什麼我早些時候問過你在運行什麼樣的客戶端。並且不會受到這些延遲的影響)

+0

然而......儘管我看到45次延遲,但我必須承認45秒有點僵硬,除非機器效率不足或過載。你沒有說明我們在談論什麼樣的機器和負載。另外,你在調試時測量這個延遲嗎?這可能會對啓動時間產生巨大影響。 –

0

如果此延遲僅適用於第一次加載(計算機啓動後),則這是由加載所有庫引起的。開始後的第一個延遲(或長時間不使用.NET後)將始終很慢。 (見Micelli答案)

延遲也可能在每次加載時引起。今天我發現互聯網連接也會導致延遲。

測量值:

  1. 無以太網和沒有WiFi連接延遲:94毫秒(Win7的)/ 1。5(操作系統)
  2. 的Windows XP:Internet連接(有代理和非標網關;不是所有的端口都允許):4-5秒(WinXP中)
  3. 與以太網相連的不是不上網:10秒( Win7的)
  4. 連接到以太網(視窗測試互聯網連接後短;在網絡圖標藍圈):30秒(WIN7)
  5. 互聯網連接(有代理和非標網關;只有少數端口允許):30秒(Win7)

*非標準網關:允許每個計算機的TCP端口和連接不同(對於WinXP和Win7不同)。

在Windows 7(x64)和WinXP上測試。我測試了它,因爲它來自客戶的投訴,並找到延遲到CoCreateInstance加載的庫在c#中,並且簽署了(用snk簽署的程序集和用於簽署可執行文件的標準證書)

另請參閱:http://social.msdn.microsoft.com/Forums/sqlserver/en-US/cda45e39-ed11-4a17-a922-e47aa2e7b325/ce-40-delay-when-cocreateinstance-on-pc-without-internet?forum=sqlce