天天看點

深入.NET程式集加載:你知道.NET程式集加載的确切時機嗎,來看看一段代碼存在的問題

這個問題是一個有關.NET公共語言運作時的問題。大家知道,.NET為了提高程式性能,所有程式集是按需加載的,也就是說在必要時在加載。但是,你知道程式集确切的加載時機嗎?絕大多數情況下,我們都不需要關心程式集的加載時機,不過,當我們在做程式自動更新的時候就碰到一些非常有趣的事情了。下面我先抛出問題。

首先,我們先來看看以下這段有問題的程式,你覺得哪有問題。我先來解釋一下這段程式的用處:

(1)在WPF的App這類的構造函數中檢測核心檔案更新并啟動OSGi.NET核心;

(2)UpdateCoreAndStartBundleRuntime的作用就是:A)更新UIShell.iOpenWorks.BundleRepositoryOpenAPI、UIShell.PageFlowService、UIShell.OSGi等程式集;B)在核心程式集更新完成後,建立一個BundleRuntime(表示OSGi.NET插件核心,來自UIShell.OSGi程式集)。

深入.NET程式集加載:你知道.NET程式集加載的确切時機嗎,來看看一段代碼存在的問題
深入.NET程式集加載:你知道.NET程式集加載的确切時機嗎,來看看一段代碼存在的問題

上面這段代碼很簡單,但是是錯誤的,下面我們稍作細微調整,代碼就能夠正常工作了。

深入.NET程式集加載:你知道.NET程式集加載的确切時機嗎,來看看一段代碼存在的問題
深入.NET程式集加載:你知道.NET程式集加載的确切時機嗎,來看看一段代碼存在的問題

正确的代碼和錯誤代碼的差異有二:

(1)_bundleRuntime的類型由BundleRuntime變為object;

(2)将UpdateCoreAndStartBundleRuntime函數拆分成兩個函數,分别為UpdateCore和StartBundleRuntime。

這兩段代碼的差别非常細微,從功能的角度來看,沒有任何的差異。各位聰明的看官,為什麼第一段代碼是錯誤的呢?這就是.NET程式集晚加載所引起的。那我們先來看看,以下這段代碼,BundleRuntime這個類型被使用并建立了一個執行個體,那麼,這個方法一旦執行完成,UIShell.OSGi(BundleRuntime類型所在程式集)這個程式集肯定被加載了。但是,确切加載時機是什麼時候?是在調用“var bundleRuntime = new BundleRuntime()”這行代碼時,UIShell.OSGi所在程式集才加載嗎?正确的答案是:UIShell.OSGi程式集加載時機是CLR進入UpdateCoreAndStartBuntime這個方法入口時,CLR會将這個方法所用到的類型的所在程式集全部加載進來。這樣問題就來了,也就是在執行UIShell.OSGi這個程式集更新之前,UpdateCoreAndStartBuntime方法剛剛調用時,UIShell.OSGi程式集就會被加載,這是,你執行對UIShell.OSGi程式集更新的時候,就會碰到異常,提示這個檔案已經被占用了。

深入.NET程式集加載:你知道.NET程式集加載的确切時機嗎,來看看一段代碼存在的問題
深入.NET程式集加載:你知道.NET程式集加載的确切時機嗎,來看看一段代碼存在的問題

我們可以在該代碼加上一個測試代碼,然後看看UIShell.OSGi是否是剛進入方法之時,執行更新之前就加載了。答案是肯定的。這段代碼很好說明了,BundleRuntime這個類型所在程式集UIShell.OSGi是在聲明這個類型的方法調用時就加載。

深入.NET程式集加載:你知道.NET程式集加載的确切時機嗎,來看看一段代碼存在的問題

以上問題的解決方法非常簡單,就是将上面兩段不同功能代碼拆分到不同的函數。此時,我們可以再來調試一下代碼。

深入.NET程式集加載:你知道.NET程式集加載的确切時機嗎,來看看一段代碼存在的問題

你可以發現拆分後,這個問題就可以解決了。好了,大家應該明白關于程式集加載的确切時機了。不過,如果大家還想追究為什麼程式集加載時機是在進入方法時,你還可以深入研究《.NET本質論》這本書,我建議大家看該書英文版的,對于深入了解CLR有非常大的幫助。

本文轉自道法自然部落格園部落格,原文連結:http://www.cnblogs.com/baihmpgy/archive/2013/05/08/3066352.html,如需轉載請自行聯系原作者

繼續閱讀