<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      C#綜合揭秘——細(xì)說進(jìn)程、應(yīng)用程序域與上下文之間的關(guān)系

      引言

      本文主要是介紹進(jìn)程(Process)、應(yīng)用程序域(AppDomain)、.NET上下文(Context)的概念與操作。
      雖然在一般的開發(fā)當(dāng)中這三者并不常用,但熟悉三者的關(guān)系,深入了解其作用,對(duì)提高系統(tǒng)的性能有莫大的幫助。
      在本篇最后的一節(jié)當(dāng)中將會(huì)介紹到三者與線程之間的關(guān)系,希望對(duì)多線程開發(fā)人員能提供一定的幫助。
      因?yàn)闀r(shí)間倉促,文中有錯(cuò)誤的地方敬請(qǐng)點(diǎn)評(píng)。

       

       

      目錄

      一、進(jìn)程的概念與作用

      二、應(yīng)用程序域

      三、深入了解.NET上下文

      四、進(jìn)程應(yīng)用程序域與線程的關(guān)系

       

       

       

      一、進(jìn)程的概念與作用

      進(jìn)程(Process)是Windows系統(tǒng)中的一個(gè)基本概念,它包含著一個(gè)運(yùn)行程序所需要的資源。進(jìn)程之間是相對(duì)獨(dú)立的,一個(gè)進(jìn)程無法直接訪問另一個(gè)進(jìn)程的數(shù)據(jù)(除非利用分布式計(jì)算方式),一個(gè)進(jìn)程運(yùn)行的失敗也不會(huì)影響其他進(jìn)程的運(yùn)行,Windows系統(tǒng)就是利用進(jìn)程把工作劃分為多個(gè)獨(dú)立的區(qū)域的。進(jìn)程可以理解為一個(gè)程序的基本邊界。

       

      1.1 Process 的屬性與方法

      在 System.Diagnostics 命名空間當(dāng)中存在Process類,專門用于管理進(jìn)程的開始、結(jié)束,訪問進(jìn)程中的模塊,獲取進(jìn)程中的線程,設(shè)定進(jìn)程的優(yōu)先級(jí)別等。
      表1.0 顯示了Process類的常用屬性:

      屬性 說明
      BasePriority 獲取關(guān)聯(lián)進(jìn)程的基本優(yōu)先級(jí)。
      ExitCode 獲取關(guān)聯(lián)進(jìn)程終止時(shí)指定的值。
      ExitTime 獲取關(guān)聯(lián)進(jìn)程退出的時(shí)間。
      Handle 返回關(guān)聯(lián)進(jìn)程的本機(jī)句柄。
      HandleCount 獲取由進(jìn)程打開的句柄數(shù)。
      HasExited 獲取指示關(guān)聯(lián)進(jìn)程是否已終止的值。
      Id 獲取關(guān)聯(lián)進(jìn)程的唯一標(biāo)識(shí)符。
      MachineName 獲取關(guān)聯(lián)進(jìn)程正在其上運(yùn)行的計(jì)算機(jī)的名稱。
      MainModule 獲取關(guān)聯(lián)進(jìn)程的主模塊。
      Modules 獲取已由關(guān)聯(lián)進(jìn)程加載的模塊。
      PriorityClass 獲取或設(shè)置關(guān)聯(lián)進(jìn)程的總體優(yōu)先級(jí)類別。
      ProcessName 獲取該進(jìn)程的名稱。
      StartInfo 獲取或設(shè)置要傳遞給Process的Start方法的屬性。
      StartTime 獲取關(guān)聯(lián)進(jìn)程啟動(dòng)的時(shí)間。
      SynchronizingObject 獲取或設(shè)置用于封送由于進(jìn)程退出事件而發(fā)出的事件處理程序調(diào)用的對(duì)象。
      Threads 獲取在關(guān)聯(lián)進(jìn)程中運(yùn)行的一組線程

       表1.0

      除了上述屬性,Process類也定義了下列經(jīng)常使用的方法:

      方法 說明
      GetProcessById 創(chuàng)建新的 Process 組件,并將其與您指定的現(xiàn)有進(jìn)程資源關(guān)聯(lián)。
      GetProcessByName 創(chuàng)建多個(gè)新的 Process 組件,并將其與您指定的現(xiàn)有進(jìn)程資源關(guān)聯(lián)。
      GetCurrentProcess 獲取新的 Process 組件并將其與當(dāng)前活動(dòng)的進(jìn)程關(guān)聯(lián)。
      GetProcesses 獲取本地計(jì)算機(jī)上正在運(yùn)行的每一個(gè)進(jìn)程列表。
      Start 啟動(dòng)一個(gè)進(jìn)程。
      Kill 立即停止關(guān)聯(lián)的進(jìn)程。
      Close 釋放與此組件關(guān)聯(lián)的所有資源。
      WaitForExit 指示 Process 組件無限期地等待關(guān)聯(lián)進(jìn)程退出。

       表1.1

      Process類的詳細(xì)信息可以參考 http://msdn.microsoft.com/zh-cn/library/system.diagnostics.process.aspx
      下面將舉例介紹一下Process的使用方式

       

      1.2 建立與銷毀進(jìn)程

      利用 Start 與Kill 方法可以簡(jiǎn)單建立或者銷毀進(jìn)程,下面例子就是利用 Start 方法啟動(dòng)記事本的進(jìn)程,并打開File.txt文件。2秒鐘以后,再使用 Kill 方法銷毀進(jìn)程,并關(guān)閉記事本。

      1         static void Main(string[] args)
      2 {
      3 Process process = Process.Start("notepad.exe","File.txt");
      4 Thread.Sleep(2000);
      5 process.Kill();
      6 }

       

      1.3 列舉計(jì)算機(jī)運(yùn)行中的進(jìn)程

      在表1.0 中可以看到,使用 GetProcesses 方法可以獲取本地計(jì)算機(jī)上正在運(yùn)行的每一個(gè)進(jìn)程列表。
      而進(jìn)程的 Id 屬性是每個(gè)進(jìn)程的唯一標(biāo)志,通過下面的方法,可以顯示當(dāng)前計(jì)算機(jī)運(yùn)行的所有進(jìn)程信息。
      因?yàn)槠P(guān)系,下面例子只獲取前10個(gè)進(jìn)程。

       1         static void Main(string[] args)
      2 {
      3 var processList = Process.GetProcesses()
      4 .OrderBy(x=>x.Id)
      5 .Take(10);
      6 foreach (var process in processList)
      7 Console.WriteLine(string.Format("ProcessId is:{0} \t ProcessName is:{1}",
      8 process.Id, process.ProcessName));
      9 Console.ReadKey();
      10 }

      運(yùn)行結(jié)果

       

      如果已知進(jìn)程的Id,就可以通過 GetProcessById 方法獲取對(duì)應(yīng)的進(jìn)程。

       1         static void Main(string[] args)
      2 {
      3 try
      4 {
      5 var process = Process.GetProcessById(1772);
      6 Console.WriteLine("Process name is:" + process.ProcessName);
      7 }
      8 catch (ArgumentException ex)
      9 {
      10 Console.WriteLine("Process is nothing!");
      11 }
      12 Console.ReadKey();
      13 }


      同樣地,你也可能通過GetProcessByName方法獲取多個(gè)對(duì)應(yīng)名稱的進(jìn)程。

      注意:如果不能找到當(dāng)前ID的進(jìn)程,系統(tǒng)就會(huì)拋出ArgumentException異常。所以使用方法 GetProcessById 獲取進(jìn)程時(shí)應(yīng)該包含在 try{...} catch{..} 之內(nèi)。

       

      1.4 獲取進(jìn)程中的多個(gè)模塊

      在表1.0 中包含了Process類的Modules屬性,通過此屬性可能獲取進(jìn)程中的多個(gè)模塊。
      這些模塊可以是以 *.dll 結(jié)尾的程序集,也可以是 *.exe 結(jié)尾的可執(zhí)行程序。
      下面的例子就是通過 Process 的 GetCurrentProcess 方法獲取當(dāng)前運(yùn)行的進(jìn)程信息,然后顯示當(dāng)前進(jìn)程的多個(gè)模塊信息。

      1         static void Main(string[] args)
      2 {
      3 var moduleList = Process.GetCurrentProcess().Modules;
      4 foreach (System.Diagnostics.ProcessModule module in moduleList)
      5 Console.WriteLine(string.Format("{0}\n URL:{1}\n Version:{2}",
      6 module.ModuleName,module.FileName,module.FileVersionInfo.FileVersion));
      7 Console.ReadKey();
      8 }

      運(yùn)行結(jié)果:

      回到目錄

       

      二、應(yīng)用程序域

      使用.NET建立的可執(zhí)行程序 *.exe,并沒有直接承載到進(jìn)程當(dāng)中,而是承載到應(yīng)用程序域(AppDomain)當(dāng)中。應(yīng)用程序域是.NET引入的一個(gè)新概念,它比進(jìn)程所占用的資源要少,可以被看作是一個(gè)輕量級(jí)的進(jìn)程。
      在一個(gè)進(jìn)程中可以包含多個(gè)應(yīng)用程序域,一個(gè)應(yīng)用程序域可以裝載一個(gè)可執(zhí)行程序(*.exe)或者多個(gè)程序集(*.dll)。這樣可以使應(yīng)用程序域之間實(shí)現(xiàn)深度隔離,即使進(jìn)程中的某個(gè)應(yīng)用程序域出現(xiàn)錯(cuò)誤,也不會(huì)影響其他應(yīng)用程序域的正常運(yùn)作。

      當(dāng)一個(gè)程序集同時(shí)被多個(gè)應(yīng)用程序域調(diào)用時(shí),會(huì)出現(xiàn)兩種情況:
      第一種情況:CLR分別為不同的應(yīng)用程序域加載此程序集。
      第二種情況:CLR把此程序集加載到所有的應(yīng)用程序域之外,并實(shí)現(xiàn)程序集共享,此情況比較特殊,被稱作為Domain Neutral。

       

      2.1 AppDomain的屬性與方法

      在System命名空間當(dāng)中就存在AppDomain類,用管理應(yīng)用程序域。下面是AppDomain類的常用屬性:

      屬性 說明
      ActivationContext 獲取當(dāng)前應(yīng)用程序域的激活上下文。
      ApplicationIdentity 獲得應(yīng)用程序域中的應(yīng)用程序標(biāo)識(shí)。
      BaseDirectory 獲取基目錄。
      CurrentDomain 獲取當(dāng)前 Thread 的當(dāng)前應(yīng)用程序域。
      Id 獲得一個(gè)整數(shù),該整數(shù)唯一標(biāo)識(shí)進(jìn)程中的應(yīng)用程序域。
      RelativeSearchPath 獲取相對(duì)于基目錄的路徑,在此程序集沖突解決程序應(yīng)探測(cè)專用程序集。
      SetupInformation 獲取此實(shí)例的應(yīng)用程序域配置信息。

      表2.0

      AppDomain類中有多個(gè)方法,可以用于創(chuàng)建一個(gè)新的應(yīng)用程序域,或者執(zhí)行應(yīng)用程序域中的應(yīng)用程序。

      方法 說明
      CreateDomain 創(chuàng)建新的應(yīng)用程序域。
      CreateInstance 創(chuàng)建在指定程序集中定義的指定類型的新實(shí)例。
      CreateInstanceFrom 創(chuàng)建在指定程序集文件中定義的指定類型的新實(shí)例。
      DoCallBack 在另一個(gè)應(yīng)用程序域中執(zhí)行代碼,該應(yīng)用程序域由指定的委托標(biāo)識(shí)。
      ExecuteAssembly 執(zhí)行指定文件中包含的程序集。
      ExecuteAssemblyByName 執(zhí)行程序集。
      GetAssemblies 獲取已加載到此應(yīng)用程序域的執(zhí)行上下文中的程序集。
      GetCurrentThreadId 獲取當(dāng)前線程標(biāo)識(shí)符。
      GetData 為指定名稱獲取存儲(chǔ)在當(dāng)前應(yīng)用程序域中的值。
      IsDefaultAppDomain 返回一個(gè)值,指示應(yīng)用程序域是否是進(jìn)程的默認(rèn)應(yīng)用程序域。
      SetData 為應(yīng)用程序域?qū)傩苑峙渲怠?/td>
      Load 將 Assembly 加載到此應(yīng)用程序域中。
      Unload 卸載指定的應(yīng)用程序域。

      表2.1

      AppDomain類中有多個(gè)事件,用于管理應(yīng)用程序域生命周期中的不同部分。

      事件 說明
      AssemblyLoad 在加載程序集時(shí)發(fā)生。
      AssemblyResolve 在對(duì)程序集的解析失敗時(shí)發(fā)生。
      DomainUnload 在即將卸載 AppDomain 時(shí)發(fā)生。
      ProcessExit 當(dāng)默認(rèn)應(yīng)用程序域的父進(jìn)程存在時(shí)發(fā)生。
      ReflectionOnlyAssemblyResolve 當(dāng)程序集的解析在只反射上下文中失敗時(shí)發(fā)生。
      ResourceResolve 當(dāng)資源解析因資源不是程序集中的有效鏈接資源或嵌入資源而失敗時(shí)發(fā)生。
      TypeResolve 在對(duì)類型的解析失敗時(shí)發(fā)生。
      UnhandledException 當(dāng)某個(gè)異常未被捕獲時(shí)出現(xiàn)。

      表2.2

      下面將舉例詳細(xì)介紹一下AppDomain的使用方式

       

      2.2 在AppDomain中加載程序集

      由表2.1中可以看到,通過CreateDomain方法可以建立一個(gè)新的應(yīng)用程序域。
      下面的例子將使用CreateDomain建立一個(gè)應(yīng)用程序域,并使用Load方法加載程序集Model.dll。最后使用GetAssemblies方法,列舉此應(yīng)用程序域中的所有程序集。

      1         static void Main(string[] args)
      2 {
      3 var appDomain = AppDomain.CreateDomain("NewAppDomain");
      4 appDomain.Load("Model");
      5 foreach (var assembly in appDomain.GetAssemblies())
      6 Console.WriteLine(string.Format("{0}\n----------------------------",
      7 assembly.FullName));
      8 Console.ReadKey();
      9 }

      運(yùn)行結(jié)果

      注意:當(dāng)加載程序集后,就無法把它從AppDomain中卸載,只能把整個(gè)AppDomain卸載。

      當(dāng)需要在AppDomain加載可執(zhí)行程序時(shí),可以使用ExecuteAssembly方法。

      AppDomain.ExecuteAssembly("Example.exe");

       

      2.3 卸載AppDomain

      通過Unload可以卸載AppDomain,在AppDomain卸載時(shí)將會(huì)觸發(fā)DomainUnload事件。
      下面的例子中,將會(huì)使用CreateDomain建立一個(gè)名為NewAppDomain的應(yīng)用程序域。然后建立AssemblyLoad的事件處理方法,在程序集加載時(shí)顯示程序集的信息。最后建立DomainUnload事件處理方法,在AppDomain卸載時(shí)顯示卸載信息。

       1         static void Main(string[] args)
      2 {
      3 //新建名為NewAppDomain的應(yīng)用程序域
      4 AppDomain newAppDomain = AppDomain.CreateDomain("NewAppDomain");
      5 //建立AssemblyLoad事件處理方法
      6 newAppDomain.AssemblyLoad +=
      7 (obj, e) =>
      8 {
      9 Console.WriteLine(string.Format("{0} is loading!", e.LoadedAssembly.GetName()));
      10 };
      11 //建立DomainUnload事件處理方法
      12 newAppDomain.DomainUnload +=
      13 (obj, e) =>
      14 {
      15 Console.WriteLine("NewAppDomain Unload!");
      16 };
      17 //加載程序集
      18 newAppDomain.Load("Model");
      19 //模擬操作
      20 for (int n = 0; n < 5; n++)
      21 Console.WriteLine(" Do Work.......!");
      22 //卸載AppDomain
      23 AppDomain.Unload(newAppDomain);
      24 Console.ReadKey();
      25 }

      運(yùn)行結(jié)果

       

      2.4 在AppDomain中建立程序集中指定類的對(duì)象

      使用CreateInstance方法,能建立程序集中指定類的對(duì)像。但使用此方法將返回一個(gè)ObjectHandle對(duì)象,若要將此值轉(zhuǎn)化為原類型,可調(diào)用Unwrap方法。
      下面例子會(huì)建立Model.dll程序集中的Model.Person對(duì)象。

       1 namespace Test
      2 {
      3 public class Program
      4 {
      5 static void Main(string[] args)
      6 {
      7 var person=(Person)AppDomain.CurrentDomain
      8 .CreateInstance("Model","Model.Person").Unwrap();
      9 person.ID = 1;
      10 person.Name = "Leslie";
      11 person.Age = 29;
      12 Console.WriteLine(string.Format("{0}'s age is {1}!",person.Name,person.Age));
      13 Console.ReadKey();
      14 }
      15 }
      16 }
      17
      18 namespace Model
      19 {
      20 public class Person
      21 {
      22 public int ID
      23 {
      24 get;
      25 set;
      26 }
      27 public string Name
      28 {
      29 get;
      30 set;
      31 }
      32 public int Age
      33 {
      34 get;
      35 set;
      36 }
      37 }
      38 }


      回到目錄

      三、深入了解.NET上下文

      3.1 .NET上下文的概念

      應(yīng)用程序域是進(jìn)程中承載程序集的邏輯分區(qū),在應(yīng)用程序域當(dāng)中,存在更細(xì)粒度的用于承載.NET對(duì)象的實(shí)體,那就.NET上下文Context。
      所有的.NET對(duì)象都存在于上下文當(dāng)中,每個(gè)AppDomain當(dāng)中至少存在一個(gè)默認(rèn)上下文(context 0)。
      一般不需要指定特定上下文的對(duì)象被稱為上下文靈活對(duì)象(context-agile),建立此對(duì)象不需要特定的操作,只需要由CLR自行管理,一般這些對(duì)象都會(huì)被建立在默認(rèn)上下文當(dāng)中。

      圖3.0

      3.2 透明代理

      在上下文的接口當(dāng)中存在著一個(gè)消息接收器負(fù)責(zé)檢測(cè)攔截和處理信息,當(dāng)對(duì)象是MarshalByRefObject的子類的時(shí)候,CLR將會(huì)建立透明代理,實(shí)現(xiàn)對(duì)象與消息之間的轉(zhuǎn)換。
      應(yīng)用程序域是CLR中資源的邊界,一般情況下,應(yīng)用程序域中的對(duì)象不能被外界的對(duì)象所訪問。而MarshalByRefObject 的功能就是允許在支持遠(yuǎn)程處理的應(yīng)用程序中跨應(yīng)用程序域邊界訪問對(duì)象,在使用.NET Remoting遠(yuǎn)程對(duì)象開發(fā)時(shí)經(jīng)常使用到的一個(gè)父類。
      此文章針對(duì)的是進(jìn)程與應(yīng)用程序域的作用,關(guān)于MarshalByRefObject的使用已經(jīng)超越了本文的范圍,關(guān)于.NET Remoting 遠(yuǎn)程對(duì)象開發(fā)可參考:“回顧.NET Remoting分布式開發(fā)”

       

      3.3 上下文綁定

      當(dāng)系統(tǒng)需要對(duì)象使用消息接收器機(jī)制的時(shí)候,即可使用ContextBoundObject類。ContextBoundObject繼承了MarshalByRefObject類,保證了它的子類都會(huì)通過透明代理被訪問。
      在第一節(jié)介紹過:一般類所建立的對(duì)象為上下文靈活對(duì)象(context-agile),它們都由CLR自動(dòng)管理,可存在于任意的上下文當(dāng)中。而 ContextBoundObject 的子類所建立的對(duì)象只能在建立它的對(duì)應(yīng)上下文中正常運(yùn)行,此狀態(tài)被稱為上下文綁定。其他對(duì)象想要訪問ContextBoundObject 的子類對(duì)象時(shí),都只能通過代透明理來操作。

      下面的例子,是上下文綁定對(duì)象與上下文靈活對(duì)象的一個(gè)對(duì)比。Example 是一個(gè)普通類,它的對(duì)象會(huì)運(yùn)行在默認(rèn)上下文當(dāng)中。而ContextBound類繼承了ContextBoundObject,它的對(duì)象是一個(gè)上下文綁定對(duì)象。ContextBound還有一個(gè)Synchronization特性,此特性會(huì)保證ContextBound對(duì)象被加載到一個(gè)線程安全的上下文當(dāng)中運(yùn)行。另外,Context類存在ContextProperties屬性,通過此屬性可以獲取該上下文的已有信息。

       1     class Program
      2 {
      3 public class Example
      4 {
      5 public void Test()
      6 {
      7 ContextMessage("Example Test\n");
      8 }
      9 //訪問上下文綁定對(duì)象測(cè)試
      10 public void Sync(ContextBound contextBound)
      11 {
      12 contextBound.Test("Example call on contextBound\n");
      13 }
      14 }
      15
      16 [Synchronization]
      17 public class ContextBound:ContextBoundObject
      18 {
      19 public void Test(string message)
      20 {
      21 ContextMessage(message);
      22 }
      23 }
      24
      25 static void Main(string[] args)
      26 {
      27 Example example = new Example();
      28 example.Test();
      29 ContextBound contextBound = new ContextBound();
      30 contextBound.Test("ContentBound Test\n");
      31 example.Sync(contextBound);
      32 Console.ReadKey();
      33 }
      34
      35 //顯示上下文信息
      36 public static void ContextMessage(string data)
      37 {
      38 Context context = Thread.CurrentContext;
      39 Console.WriteLine(string.Format("{0}ContextId is {1}", data, context.ContextID));
      40 foreach (var prop in context.ContextProperties)
      41 Console.WriteLine(prop.Name);
      42 Console.WriteLine();
      43 }
      44 }

      運(yùn)行結(jié)果

      由運(yùn)行結(jié)果可以發(fā)現(xiàn),example對(duì)象一般只會(huì)工作于默認(rèn)上下文context 0 當(dāng)中,而contextBound則會(huì)工作于線程安全的上下文 context 1當(dāng)中。當(dāng)example需要調(diào)用contextBound對(duì)象時(shí),就會(huì)通過透明代理把消息直接傳遞到context 1中。
       

      回到目錄

      四、進(jìn)程、應(yīng)用程序域、線程的相互關(guān)系

      4.1 跨AppDomain運(yùn)行代碼

      在應(yīng)用程序域之間的數(shù)據(jù)是相對(duì)獨(dú)立的,當(dāng)需要在其他AppDomain當(dāng)中執(zhí)行當(dāng)前AppDomain中的程序集代碼時(shí),可以使用CrossAppDomainDelegate委托。把CrossAppDomainDelegate委托綁定方法以后,通過AppDomain的DoCallBack方法即可執(zhí)行委托。

       1         static void Main(string[] args)
      2 {
      3 Console.WriteLine("CurrentAppDomain start!");
      4 //建立新的應(yīng)用程序域?qū)ο?/span>
      5 AppDomain newAppDomain = AppDomain.CreateDomain("newAppDomain");
      6 //綁定CrossAppDomainDelegate的委托方法
      7 CrossAppDomainDelegate crossAppDomainDelegate=new CrossAppDomainDelegate(MyCallBack);
      8 //綁定DomainUnload的事件處理方法
      9 newAppDomain.DomainUnload += (obj, e) =>
      10 {
      11 Console.WriteLine("NewAppDomain unload!");
      12 };
      13 //調(diào)用委托
      14 newAppDomain.DoCallBack(crossAppDomainDelegate);
      15 AppDomain.Unload(newAppDomain) ;
      16 Console.ReadKey();
      17 }
      18
      19 static public void MyCallBack()
      20 {
      21 string name = AppDomain.CurrentDomain.FriendlyName;
      22 for(int n=0;n<4;n++)
      23 Console.WriteLine(string.Format( " Do work in {0}........" , name));
      24 }

      運(yùn)行結(jié)果

       

      4.2 跨AppDomain的線程

      線程存在于進(jìn)程當(dāng)中,它在不同的時(shí)刻可以運(yùn)行于多個(gè)不同的AppDomain當(dāng)中。它是進(jìn)程中的基本執(zhí)行單元,在進(jìn)程入口執(zhí)行的第一個(gè)線程被視為這個(gè)進(jìn)程的主線程。在.NET應(yīng)用程序中,都是以Main()方法作為入口的,當(dāng)調(diào)用此方法時(shí) 系統(tǒng)就會(huì)自動(dòng)創(chuàng)建一個(gè)主線程。線程主要是由CPU寄存器、調(diào)用棧和線程本地存儲(chǔ)器(Thread Local Storage,TLS)組成的。CPU寄存器主要記錄當(dāng)前所執(zhí)行線程的狀態(tài),調(diào)用棧主要用于維護(hù)線程所調(diào)用到的內(nèi)存與數(shù)據(jù),TLS主要用于存放線程的狀態(tài)信息。
      關(guān)于線程的介紹,可參考 “C#綜合揭秘——細(xì)說多線程(上)”、“C#綜合揭秘——細(xì)說多線程(下)”

      下面的例子將介紹一下如何跨AppDomain使用線程,首先建立一個(gè)ConsoleApplication項(xiàng)目,在執(zhí)行時(shí)輸入當(dāng)前線程及應(yīng)用程序域的信息,最后生成Example.exe的可執(zhí)行程序。

      1         static void Main(string[] args)
      2 {
      3 var message = string.Format(" CurrentThreadID is:{0}\tAppDomainID is:{1}",
      4 Thread.CurrentThread.ManagedThreadId, AppDomain.CurrentDomain.Id);
      5 Console.WriteLine(message);
      6 Console.Read();
      7 }

      然后再新建一個(gè)ConsoleApplication項(xiàng)目,在此項(xiàng)目中新一個(gè)AppDomain對(duì)象,在新的AppDomain中通過ExecuteAssembly方法執(zhí)行Example.exe程序。

       1         static void Main(string[] args)
      2 {
      3 //當(dāng)前應(yīng)用程序域信息
      4 Console.WriteLine("CurrentAppDomain start!");
      5 ShowMessage();
      6
      7 //建立新的應(yīng)用程序域?qū)ο?/span>
      8 AppDomain newAppDomain = AppDomain.CreateDomain("newAppDomain");
      9 //在新的應(yīng)用程序域中執(zhí)行Example.exe
      10 newAppDomain.ExecuteAssembly("Example.exe");
      11
      12 AppDomain.Unload(newAppDomain);
      13 Console.ReadKey();
      14 }
      15
      16 public static void ShowMessage()
      17 {
      18 var message = string.Format(" CurrentThreadID is:{0}\tAppDomainID is:{1}",
      19 Thread.CurrentThread.ManagedThreadId, AppDomain.CurrentDomain.Id);
      20 Console.WriteLine(message);
      21 }

      運(yùn)行結(jié)果

      可見,ID等于9的線程在不同時(shí)間內(nèi)分別運(yùn)行于AppDomain 1與AppDomain 2當(dāng)中。

       

      4.3 跨上下文的線程

      線程既然能夠跨越AppDomain的邊界,當(dāng)然也能跨越不同的上下文。
      下面這個(gè)例子中,線程將同時(shí)運(yùn)行在默認(rèn)上下文與提供安全線程的上下文中。

       1     class Program
      2 {
      3 [Synchronization]
      4 public class ContextBound : ContextBoundObject
      5 {
      6 public void Test()
      7 {
      8 ShowMessage();
      9 }
      10 }
      11
      12 static void Main(string[] args)
      13 {
      14 //當(dāng)前應(yīng)用程序域信息
      15 Console.WriteLine("CurrentAppDomain start!");
      16 ShowMessage();
      17
      18 //在上下文綁定對(duì)象中運(yùn)行線程
      19 ContextBound contextBound = new ContextBound();
      20 contextBound.Test();
      21 Console.ReadKey();
      22 }
      23
      24 public static void ShowMessage()
      25 {
      26 var message = string.Format(" CurrentThreadID is:{0}\tContextID is:{1}",
      27 Thread.CurrentThread.ManagedThreadId, Thread.CurrentContext.ContextID);
      28 Console.WriteLine(message);
      29 }
      30 }

      運(yùn)行結(jié)果

       

      本篇總結(jié)

      進(jìn)程(Process)、線程(Thread)、應(yīng)用程序域(AppDomain)、上下文(Context)的關(guān)系如圖5.0,一個(gè)進(jìn)程內(nèi)可以包括多個(gè)應(yīng)用程序域,也有包括多個(gè)線程,線程也可以穿梭于多個(gè)應(yīng)用程序域當(dāng)中。但在同一個(gè)時(shí)刻,線程只會(huì)處于一個(gè)應(yīng)用程序域內(nèi)。線程也能穿梭于多個(gè)上下文當(dāng)中,進(jìn)行對(duì)象的調(diào)用。

      雖然進(jìn)程、應(yīng)用程序域與上下文在平常的開發(fā)中并非經(jīng)常用到,但深入地了解三者的關(guān)系,熟悉其操作方式對(duì)合理利用系統(tǒng)的資源,提高系統(tǒng)的效率是非常有意義的。
      尤其是三者與線程之間的關(guān)系尤為重要,特別是在一個(gè)多線程系統(tǒng)中,如果不能理清其關(guān)系而盲目使用多線程,容易造成資源搶占與死鎖之類的錯(cuò)誤。

       圖5.0

      希望本篇文章對(duì)相關(guān)的開發(fā)人員有所幫助。
      對(duì) .NET 開發(fā)有興趣的朋友歡迎加入QQ群:162338858 同探討 !

      回到目錄

      C#綜合揭秘

      通過修改注冊(cè)表建立Windows自定義協(xié)議
      Entity Framework 并發(fā)處理詳解

      細(xì)說進(jìn)程、應(yīng)用程序域與上下文

      細(xì)說多線程(上)

      細(xì)說多線程(下)
      細(xì)說事務(wù)
      深入分析委托與事件

       

      作者:風(fēng)塵浪子
      http://www.rzrgm.cn/leslies2/archive/2012/03/06/2379235.html 

      原創(chuàng)作品,轉(zhuǎn)載時(shí)請(qǐng)注明作者及出處




      posted on 2012-03-06 09:36  風(fēng)塵浪子  閱讀(49079)  評(píng)論(61)    收藏  舉報(bào)

      導(dǎo)航

      主站蜘蛛池模板: 免费观看一级欧美大| 成人性无码专区免费视频| 久久人人爽人人爽人人av| 一道本AV免费不卡播放| 鲁鲁网亚洲站内射污| 亚洲一级片一区二区三区| 久久精品国产一区二区蜜芽| 樱桃视频影院在线播放| 久久久天堂国产精品女人| 色综合久久一区二区三区| 四虎国产精品永久在线下载| 日产国产一区二区不卡| 亚洲精品蜜桃久久久久久| 国产在线亚州精品内射| 中文字幕乱码一区二区免费| 好紧好湿太硬了我太爽了视频| 日本一区二区三区在线看| 宝贝腿开大点我添添公视频免| 人妻少妇精品专区性色av| 色悠悠国产精品免费观看| 亚洲国产在一区二区三区| 中国老太婆video| 最新亚洲人成网站在线观看| 免费无码一区无码东京热| 亚洲综合网一区中文字幕| 妺妺窝人体色WWW看人体| 精品国产午夜福利在线观看| 激情在线网| 欧美区一区二区三区| 十八禁午夜福利免费网站| 人妻体内射精一区二区三四| 老司机午夜福利视频| 亚洲激情国产一区二区三区| 玩弄放荡人妻少妇系列| 久久精品蜜芽亚洲国产AV| 日本新janpanese乱熟| 激情亚洲专区一区二区三区| 国产中文字幕一区二区| 国产成人A在线视频免费| 日日碰狠狠添天天爽五月婷| 影音先锋大黄瓜视频|