1.2. .net和C#对线程的支持(学习)

本节需要了解:

  •   什么是System.AppDomain类,可以使用该类做什么
  •   .Net运行库是如何监控线程的

  1. System.AppDomain 类

    之前了解,进程是内存和资源的一个物理独立的部分,后来又提到一个进程至少有一个线程。

    当Microsoft设计.Net Framewrok时,新增了一个隔离层,称为应用程序域或AppDomain。应用程序不是进程那样是一个物理独立的部分,而是进程内部的一个逻辑独立部分。在一个进程中可以存在多个应用程序域。通常,标准的进程不使用代理,就不可以访问其它进程的数据(之前说明了,进程都是独立的操作数据的).使用代理会耗费很多系统资源,编码也会变得很复杂。但是引入应用程序的概念,就可以在同一个进程中启动好几个应用程序域,进程所提供的同一个隔离区域可以和应用程序一起使用。线程可以跨多个应用程序域来执行,且不需要耗费因线程内部通信而产生的系统开销。

    Microsoft把这些应用程序域的所有功能都封装在一个名为System.AppDomain的类中。为了了解一下System.AppDomain

    1.1.设置AppDomain数据

      创建一个控制台MyAppDomain:

      

namespace MyAppDomain
{
    public class Program
    {
        public AppDomain Domain;
        public int ThreadId;
        public void SetDomainDate(string vName, string vValue)
        {
            Domain.SetData(vName, (object)vValue);
            ThreadId = AppDomain.GetCurrentThreadId();
        }

        public T GetDomainData<T>(string vName)
        {
            return (T)Domain.GetData(vName);
        }
        static void Main(string[] args)
        {
            var DataName = "MyData";
            var DataValue = "Some Data";
            Console.WriteLine("开始");
            Program obj = new Program();
            obj.Domain = AppDomain.CurrentDomain;
            obj.SetDomainDate(DataName, DataValue);
            Console.WriteLine("输出System.AppDomain数据");
            Console.WriteLine(string.Format("数据存储的key:{0},取出的值为:{1},获取当前线程id:{2}",DataName,obj.GetDomainData<string>(DataName),obj.ThreadId));
            Console.Read();
            
        }
    }
}

执行之后会输出:
    开始

    输出System.AppDomain数据

    数据存储的key:MyData,取出的值为:Some Data,获取当前线程id:22388(ThreadId是根据当前系统环境自动分配而获取)

 1.2.在指定的应用程序域中执行代码

    创建新的应用程序域,着重介绍在新建的AppDomain中创建新线程时的有关行为,源代码:

    

namespace CreateAppDomians
{
    class Program
    {
        static void Main(string[] args)
        {
            AppDomain DomainA;
            DomainA = AppDomain.CreateDomain("MyDomainA");//创建一个应用程序域,域名为:MyDomainKeyA
            string stringA = "值1";
            DomainA.SetData("DomainKey", stringA);

            CommonCallBack();//直接调用这方法会创建一个新应用程序域,这时候就有两个应用程序了

            CrossAppDomainDelegate delegateA = new CrossAppDomainDelegate(CommonCallBack);//这里使用跨应用程序域的调用的
            DomainA.DoCallBack(delegateA);//委托把另一程序域委托给由指定的应用程序执行
           
            Console.Read();
        }

        public static void CommonCallBack() {
            AppDomain Domain;
            Domain = AppDomain.CurrentDomain;
            Console.WriteLine("获取当前线程保存的值value:'{0}',获取可执行程序的名称:{1},ThreadId:{2}", Domain.GetData("DomainKey"), Domain.FriendlyName.ToString(), AppDomain.GetCurrentThreadId());
        }
    }
}

输出的结果为:

    获取当前线程保存的值value:'',获取可执行程序的名称:CreateAppDomians.exe,ThreadId:13007

    获取当前线程保存的值value:'值1',获取可执行程序的名称:MyDomainA,ThreadId:13007

从再次调用GetCurrentThreadId()方法。在程序输出结果中,无论当中的应用程序执行,得到的线程的ID都是一样的。这一点很重要,因为这不仅意味着AppDomain可以有零个或多个线程,而且能够跨不同的域来执行线程。

2.线程管理与.net运行库

  .Net Framework不仅提供了对自由线程的进程和逻辑应用程序的支持,还提供了处理线程的对象,这些对象表示都是System.Threading.Thread类的实例。而在了解System.Threading.Thread之前先要了解托管线程和非托管线程的关系。 说得笼统点,非托管线程(在.net外部创建)是如何与托管线程类的实例(表示运行在.net CRL内部的线程)发生关联。

    当非托管线程在托管线程中执行时,运行库会检查TLS(线程本地存储器),确定是否存在托管的对象。如果找到了一个托管线程对象,运行库就使用那个线程。如果没有的就创建一个并使用。这个过程很简单,但是必要的。因为运行库不为这类内部调用和创建线程,就不能在托管的环境中标识线程,更不能控制它了。

 

 

    

    

posted on 2014-01-03 17:32  紫色的冰  阅读(242)  评论(0编辑  收藏  举报