本文章是由機器翻譯。
深究 CLR
同處理序並行
Jesse Kaplan 和 Luiz Fernando Santos
的 CLR 團隊部落格 上張貼問題或意見。
我們建置.NET Framework 4,我們面臨更困難的問題之一維護與舊版本仍然新增新的功能時相容性。 我們遵循嚴格要求核准的任何變更,可能會帶來相容性問題的處理程序 — 大部分而遭到拒絕 — 並執行相容性實驗室與數百個真實的應用程式尋找任何意外的符號。
但每次我們修正 Bug ’s 某些應用程式相依於該錯誤行為的風險。 有時候應用程式需要我們對抗,警告如私用的 API 行為或例外狀況的描述文字的相依性。
由於引進.NET Framework,我們有很好的解決方案,為應用程式相容性:允許多個版本的.NET Framework 同一部電腦上安裝一次。 這可讓兩個不同的應用程式,建置對兩個不同的版本並將其安裝於以適當版本對每個執行的其中一部電腦。
增益集的問題
這適用於正常當每個應用程式取得自己的處理序,但增益集是更難的問題。 想像一下您執行程式時,例如裝載 COM 增益集,包括 Outlook Managed COM 增益集,且您有兩個版本的執行階段 — 和增益集針對每一個內建 — 安裝在您的機器上。 您應該選擇哪一種執行階段? 載入一個較新增益集上較舊的執行階段清楚地不會運作。
在另一方面,因為的相容性高階較舊的增益集將通常執行細緻較新的執行階段上。 若要讓所有的增益集工作的最佳機會,我們總是選擇最新的執行階段的 Managed COM 啟動。 即使您只有舊增益集安裝有會為我們知道當啟動該增益集取得,所以最新的執行階段仍取得載入沒有辦法。
此啟動原則的一個不幸副作用是當使用者安裝新的應用程式使用新版本的執行階段,完全無關的應用程式,使用 Managed COM 增益集,建置對較舊版本,突然開始在較新的執行階段上執行並可能會失敗。
.NET Framework 3.0 和 3.5,我們解決這個問題,透過極為嚴格的原則:每次發行的版本是加法類和只新增新 assemblies 至含有相同的執行階段下方先前的版本。 安裝執行.NET Framework 2.0 的電腦上時,這會防止任何相容性問題。 這表示在.NET Framework 3.5 上執行應用程式時, 您正在真正執行它對 2.0] 執行階段與它的上方幾個額外的組件。 不過,這也表示我們 couldn’t 創新.NET 2.0 組件只是在時間 (JIT) 和基底類別程式庫中包含這類的記憶體回收] 行程的關鍵功能中。
與.NET Framework 4 我們已實作一個可讓包括永遠不會破壞現有的增益集的高相容的方法, and 也能讓我們在核心創新。 我們現在可以在相同的處理序中執行.NET 2.0 和.NET 4 增益集,在同一時間。 我們呼叫此方法處理中--並排或在程序 SxS。
雖然在程序 SxS 能解決最常見的相容性問題,它 doesn’t 修正所有項目。 在本專欄中我們更描述有關為何我們決定建置程序在 SxS、 它的運作方式和哪些問題它 doesn’t 解決。 撰寫一般的應用程式或增益集的人員,在程序 SxS 多半只是運作 — 右所有自動發生的事情。 對於那些您正在撰寫可以利用在程序 SxS 的主機的我們也描述更新裝載 API,並提供一些指導方針來使用它們。
眷顧 Ozzie ’s Office 來回存取時
最遲於 2005 年幾乎所有高階 Microsoft 主管所以突然無法檢查任何其主要的機器上的電子郵件。 沒有什麼理由每當它們開啟的 Outlook 它會墜毀重新啟動,並將然後墜毀在連續迴圈中。 有個表面上可能已被造成這沒有最近更新 Outlook 或任何其他動作。 它已很快就追蹤往下到由受管理的增益集被擲回的 Managed 例外狀況。 我的朋友 「 礦坑 」 指的是欄 co-author Jesse Kaplan — Ed. 從 Visual Studio 工具為 Office VSTO 小組 — 負責為辦公室的受管理的增益集 — 已傳送給診斷此問題,在其中一個此 Bug 的最顯著的受害者的電腦上:眷顧 Ozzie,在時間是主要的技術主管。
一旦眷顧 ’s 辦公室在我的朋友是快速能夠判斷.NET Framework 2.0 的 Beta 版本必須透過一個內部的 Beta 版] 程式被部署,而且他識別哪一個 Office 增益集造成問題。 為以上任一相容性 PMs CLR 團隊我安裝增益集,並從該處花費。
我們快速地決定何者發生錯誤:增益集必須競爭情形,它啟動向上九個不同的執行緒,而且之後開始初始化資料每個執行緒處理 (請參閱 的 圖 1)。 coders 了幸運與計時,但一旦安裝.NET Framework 2.0 增益集已自動向前復原至.NET 2.0 我上述原因。 .NET 2.0 在以便潛在的競爭情形啟動來啟動執行緒,稍微快些,但一致地浮現。
圖 1 的 程式碼從 [Office 增益集
Thread [] threads = new Thread[9];
for (int i=0; i<9; i++)
{
Worker worker = new Worker();
threads[i] = new ThreadStart(worker.Work);
threads[i].Start(); //This line starts the thread executing
worker.identity =i; //This line initializes a value that
//the thread needs to run properly
}
此應用程式失敗主導在相容性回家硬課程:不論如何硬我們試著避免進行非可以中斷應用程式的行為變更,簡單的事情如效能改進可以公開中應用程式和增益集,會讓其失敗的錯誤時對執行以外執行階段建置和測試上它們的物件。 我們實現時發生為我們發展平台的任何有意義的方式,並確保在最新版本上執行像是一個以上的應用程式可以完全沒有辦法。
中斷的安裝
我們相容性測試期間,我們附在執行過正常如果.NET 2.0 已安裝之後的應用程式,但如果應用程式已有 1.1 (應用程式所用以建置針對版本) 和 2.0 版的電腦上安裝失敗的應用程式時。 共花費一段時間來算出什麼生上,但是我們追蹤向到 2.0 和這個時間問題尋找架構目錄內部已,再次,向前浮動,安裝程式已執行的程式碼有點問題。
偵測邏輯已清楚易損壞及實際錯誤,您可以在這裡看到:
string sFrameworkVersion = System.Environment.Version.ToString();
string sWinFrameworkPath = session.Property["WindowsFolder"] +
"Microsoft.NET\\Framework\\v" +
sFrameworkVersion.Substring(0,8) + "\\";
但即使之後修正該 Bug,應用程式仍然無法在安裝之後正確執行。 這裡 ’s 修正程式:
string sWinFrameworkPath = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
結果,安裝程式已尋求架構目錄以取得 caspol.exe 的路徑,並授與應用程式在該架構中執行的權限。 它甚至打破之後尋找路徑,因為它有只授予本身 2.0 的 CLR 上執行,雖然在 1.1 版的 CLR 上執行應用程式本身的權限。 這裡 ’s 問題程式碼:
System.Diagnostics.Process.Start(sWinFrameworkPath + "caspol.exe " + casPolArgs);
透過同處理序-並存相容性
如我們附了解,所有這些情況中造成問題的核心問題是它是不可能使任何重大變更或加入我們的平台的項目,仍確保 [最新版本可能也像舊版一樣執行任何應用程式。
從開始.NET Framework 嘗試解決這個問題的機器上架構的多個版本的支援-並存安裝由,然後讓每個選擇哪一個版本的應用程式想要在執行。
不幸的是每個處理程序的一個執行階段的限制是用如管理 COM 元件和擴充性案例了多個獨立的應用程式相同的處理序中執行的地方是能為每一無單一選擇。其中有些百分比會中斷某些元件已不會取得他們希望在執行階段以及,不論如何硬我們嘗試維持相容性是用這項限制。
載入多個處理序中執行階段版本我們新的能力可解決這些問題。
許多原則
若要協助您更加瞭解一些我們所做的決策和我們描述資料行中稍後詳細的行為,’s 討論指導原則我們持有雖然設計這項功能很有用。
- 安裝新版本的.NET Framework 應該有沒有影響現有的應用程式。
- 應用程式和增益集應該針對架構建置和測試對它們的版本執行。
- 不過在一些情況下,例如使用我們 can’t 對架構程式庫建置對抗,執行程式碼的程式庫時所以我們必須仍然努力百分之百的回溯相容性。
所有現有的應用程式和增益集應該繼續執行對架構它們建置和設定為上執行,除非他們特別要求輸入它,否則不應該看到新版本的版本。這一直規則的 Managed 應用程式,但現在它也適用於 Managed COM 增益集和執行階段裝載 API 的消費者。
除了確定對建置與執行階段版本的應用程式執行,我們仍然必須請確定它是容易轉換至較新的執行階段,因此我們有保留相容性的.NET Framework 4 一樣高一樣或它是使用.NET 2.0 越高。
行為的概觀
.NET Framework 4 執行階段 — 以及所有未來的執行階段 — 將能夠執行同處理序彼此。雖然我們沒有回連接埠這項功能較舊的執行階段 (1.0 透過 3.5),我們是否確定要 4 欠就可以執行同處理序與任何單一較舊的執行階段。亦即您可以載入 4、 5 和 2.0 在相同的處理序中,但無法載入 1.1 和 2.0 在相同的處理序中。透過 3.5 所有.NET 架構 2.0 在 2.0 的執行階段上執行,並因此有彼此,沒有衝突,如 的 圖 2 所示。
.NET Framework 版本 | ||||
1.1 | 2.0 到 3.5 | 4 | 5 | |
1.1 | N/A | 不可以 | Yes | Yes |
2.0 到 3.5 | 不可以 | N/A | Yes | Yes |
4 | Yes | Yes | N/A | Yes |
5 | Yes | Yes | Yes | N/A |
圖 2 在相同的處理程序將這些執行階段負載吗?
沒有現有的應用程式或元件,安裝.NET Framework 4 執行階段時應該注意任何差異:它們應該繼續取得建置對抗無論使用何種執行階段。應用程式及建置.NET 4 對 Managed 的 COM 元件就會在 4 的執行階段上執行。想要與 4 的執行階段互動的主機將需要特別要求。
什麼會同處理序-並存平均數給您?
結束使用者和系統管理員: 您現在可以有信心,當您安裝新版本的執行階段是獨立或與應用程式,它將不會有影響您的電腦上,所有現有的應用程式會繼續執行之前所顯示的一樣。
應用程式開發人員: 在程序 SxS 對應用程式開發人員幾乎沒有影響。應用程式永遠有預設的架構在其所建置,且這未變更版本對執行。唯一的變更,我們所做的行為會影響應用程式開發人員是我們將不再自動執行當原始的版本不存在時,針對較舊的執行階段在較新版本上建置的應用程式。而是我們會提示使用者下載原始版本,並提供要輕鬆執行這項操作的連結。
我們仍然提供組態選項,可讓您指出您想要針對,執行您應用程式,所以在較新的執行階段上執行較舊的應用程式架構的哪一個版本,但我們 won’t 自動執行。
程式庫開發人員和客戶: 在程序 SxS 不能解決相容性程式庫開發人員所面臨的問題。直接由應用程式載入任何文件庫 — 任一個透過直接參考或一個 Assembly.Load*—will 繼續直接載入執行階段和應用程式網域的應用程式載入它。這表示如果應用程式對.NET Framework 4 執行階段執行重新編譯,而且仍然有相依的組件對.NET 2.0 建置,這些相依性會載入.NET 4 執行階段上。因此,我們仍然建議測試程式庫 against 想要支援的架構的所有版本。這是我們持續維護我們高層級的回溯相容性的理由。
受管理的 COM 元件開發人員專區: 在過去自動會針對最新版本的安裝在電腦上執行階段執行這些元件。現在,pre-.NET Framework 4 元件仍然取得啟動對最新的執行階段 (3.5 吋或更早的版本),而且所有較新的元件將會載入與建置,版本 的 圖 3 所示。
|
||||
|
||||
|
||||
|
||||
|
圖 3 Managed COM 元件和執行階段交互操作性
殼層延伸開發人員: 殼層延伸是套用到各種不同的內部 Windows 殼層的擴充性點的一般名稱。兩個常見的範例是新增至檔案和資料夾及那些提供自訂的圖示按滑鼠右鍵內容功能表或圖示覆疊檔案及資料夾的延伸。
這些擴充功能透過標準的 COM 模型公開,而其定義的特性是它們會載入同處理序與任何應用程式。是這最後一位元和事實該只有一個 CLR 已被允許每個處理序造成受管理的殼層延伸的問題。以詳細說明:
- 殼層延伸寫入對執行階段版本 N。
- 它必須是在任何應用程式中包括那些建置版本對稍後或更早版本比 N。 機器上載入
- 如果應用程式所用以建置針對更新的版本比副檔名,事情是通常 [確定],除非有相容性問題。
- 如果應用程式所用以建置針對較早版本的延伸模組,就一定能夠失敗 — 較舊的執行階段顯然無法執行建置的較新的一的殼層延伸。
- 如果某種方式殼層延伸已載入應用程式 ’s Managed 程式碼元件之前,其所選擇的架構版本可能會與應用程式發生衝突,並中斷所有項目。
這些問題領導我們正式建議針對 — 並不支援 — 同處理序的殼層延伸使用開發 Managed 程式碼。如您在此解釋該問題的 MSDN 論壇中所見,這是對於我們和我們的客戶是痛苦的選擇: https://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/1428326d-7950-42b4-ad94-8e962124043e.殼層延伸是非常普遍,其中一個最後一個將放某些類型的應用程式的開發人員會被迫寫入原生程式碼。不幸的是,因為的允許每個處理程序只有一個執行階段的我們限制我們無法支援它們。
能夠與任何其他執行階段的程序中有多個執行階段,我們現在可以提供一般支援書寫受管理的殼層延伸 — 甚至是那些執行同處理序與電腦上的任意應用程式。我們仍不支援寫入殼層延伸早於.NET Framework 4 使用任何版本,因為這些版本的執行階段不會載入同處理序與其他及會導致失敗的許多情況。
開發人員的殼層延伸 Managed 和原生,仍然必須特別注意,並確保它們能夠在各種不同的環境中執行,並與其他人合作。如我們會得到更接近放開製造 (RTM),我們將提供指南和範例,可以幫助您開發也在 Windows eco 系統中播放的高品質受管理的殼層延伸。
Managed 程式碼的主機: 如果您裝載使用原生 COM 啟動的 Managed 程式碼,您不會執行任何特殊處理多個執行階段的動作。您永遠在進行和執行階段載入它們根據列在 的 圖 3 規則來,您可以只是來啟動元件。
如果您曾經使用任何裝載 API 我們 pre-.NET Framework 4,您可能已經發現它們都假設該只有一個執行階段將曾經載入程序中。因此,如果您裝載執行階段使用我們的原生 API,您必須修改您的主機會在程序 SxS-感知。我們新的方法,在處理程序中擁有多個執行階段的一部分我們已經取代舊的、 單一執行階段感知裝載 API,並加入一組新的裝載 API 設計來幫助您管理多重執行階段環境。MSDN 將會有完整的文件,以新的 API,但會是相當容易使用如果您有使用目前的經驗。
我們面臨開發程序在 SxS 時最有趣的挑戰之一是如何更新現有、 單一執行階段感知裝載 API 行為的問題。一系列的選項是可用的但是時遵循上述原則仍配置稍早在本專欄中我們從下列方針:API 應該行為,讓它們在電腦上安裝.NET Framework 4 時, 傳回他們以前的確切行為。也就是說它們僅能知道每個處理程序中的一個執行階段,而且即使您將先前已經啟動機器上最新的執行階段的方式來使用它們,它們會只提供您最新的執行階段與版本早於 4。
仍然有 「 連結 」 這些 API 到.NET Framework 4 執行階段藉由明確地傳遞至它們的 [4 的版本號碼,或將您的應用程式設定以特定方式的方式,但是一次,這會發生只当您要特別要求 4 的執行階段,而且不要求 「 最新 」。
在摘要: 程式碼將使用現有的裝載 API 會繼續運作當.NET Framework 4 已安裝,但會取得處理序的檢視,將會看到只有一個執行階段載入。而且,來維護此相容性,它們通常都能夠只互動 pre-4 版本。為每個這些較舊的 API 都選擇版本詳細資料將可在 MSDN,但是上述幾個規則應該幫助您瞭解我們如何決定這些行為。如果要與多重執行階段互動則需要將移至新的 API。
C + + / CLI 開發人員: C + + / CLI 或 Managed C + + 是一種有趣的技術,可以讓開發人員混用相同的組件中的 Managed 和原生程式碼及管理多半是不需要開發人員互動兩者之間轉換。
因為的該架構上都會有限制您如何在這個新世界中使用這些組件。其中一個最基本的問題是,如果我們允許每個處理程序好幾次載入這些組件,我們仍然需要維護 Managed 和原生資料區段間的隔離。這表示這不允許由原生 Windows 載入器載入兩次,這兩個區段。為何我們有下列限制的完整詳細資料不在本專欄的範圍,但其他地方如我們會得到更接近 RTM 會可用。
基本限制是該 pre-.NET Framework 2.0 架構 C + + / CLI 的組件可以只載入在.NET 2.0 執行階段上。如果您提供一個 2.0 C + + / CLI 程式庫和想要從 4 可消耗的而且超越,您需要重新編譯與您想要載入中的每個版本。如果您使用其中一個程式庫,您將會是需要從程式庫開發人員取得更新的版本或,最後的方法是: 您可以設定來封鎖 pre-4 從您的處理序的執行階段應用程式。
沒有更多麻煩
Microsoft.NET Framework 4 還最回溯相容發行的.NET。藉由將在程序 SxS 帶到表格,Microsoft 保證安裝.NET 4 的簡單的動作並不會中斷任何現有的應用程式,並且已經安裝在電腦上的所有項目會運作,以及它未之前。
一般使用者不再需要擔心安裝架構 — 不論是直接或與應用程式需要用它的 — 會中斷任何應用程式已經在電腦上。
企業及 IT 專業人員可以快或當他們想而不必擔心與另一個衝突的不同應用程式所用的不同版本為逐漸採用架構的新版本。
開發人員可以使用最新版本的架構來建置其應用程式,而且可以 reassure 他們將會安全部署的客戶。
最後,主機和增益集程式開發人員可以是架構的能輕鬆地了解他們會取得他們想而不影響其他,人,好讓它們成為確信其程式碼會持續工作如即使安裝了新的版本,架構版本。
Jesse Kaplan 為程式管理員的管理/原生交互操作性 CLR 小組在 Microsoft。他過去的責任包括相容性和擴充性。
Luiz Santos* 先前部份 CLR 團隊,是在 SQL 連線能力] 小組中的程式管理員其中他是負責提供 ADO.NET 管理者,包括 SqlClient、 ODBCClient 和 OLEDBClient。*
感謝下列技術專家來檢閱文件: Joshua Goodman、 Simon Hall 和 Sean Selitrennikoff