当前位置:首页 > C#编程 > C#/.net框架 > 正文内容

细说进程、应用程序域与上下文之间的关系(四)——进程应用程序域与线程的关系

Jorge2年前 (2022-05-08)C#/.net框架724

目录

一、进程的概念与作用

二、应用程序域

三、深入了解.NET上下文

四、进程应用程序域与线程的关系

 

四、进程、应用程序域、线程的相互关系

4.1 跨AppDomain运行代码

在应用程序域之间的数据是相对独立的,当需要在其他AppDomain当中执行当前 AppDomain中的程序集代码时,可以使用CrossAppDomainDelegate委托。把CrossAppDomainDelegate委托 绑定方法以后,通过AppDomain的DoCallBack方法即可执行委托。

C#
static void Main(string[] args)
         {
             Console.WriteLine("CurrentAppDomain start!");             //建立新的应用程序域对象
             AppDomain newAppDomain = AppDomain.CreateDomain("newAppDomain");             //绑定CrossAppDomainDelegate的委托方法
             CrossAppDomainDelegate crossAppDomainDelegate=new CrossAppDomainDelegate(MyCallBack);             //绑定DomainUnload的事件处理方法
             newAppDomain.DomainUnload += (obj, e) =>
             {
                 Console.WriteLine("NewAppDomain unload!");
             };             //调用委托
             newAppDomain.DoCallBack(crossAppDomainDelegate);
             AppDomain.Unload(newAppDomain) ;
             Console.ReadKey();
         } 
         static public void MyCallBack()
         {             string name = AppDomain.CurrentDomain.FriendlyName;             for(int n=0;n<4;n++)
             Console.WriteLine(string.Format( "  Do work in {0}........" , name));
         }

运行结果

 

4.2 跨AppDomain的线程

线程存在于进程当中,它在不同的时刻可以运行于多个不同的AppDomain当中。它是进程 中的基本执行单元,在进程入口执行的第一个线程被视为这个进程的主线程。在.NET应用程序中,都是以Main()方法作为入口的,当调用此方法时 系统就会自动创建一个主线程。线程主要是由CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状 态信息。
关于线程的介绍,可参考 “C#综合揭秘——细说多线程(上)”、“C#综合揭秘——细说多线程(下)”

下面的例子将介绍一下如何跨AppDomain使用线程,首先建立一个ConsoleApplication项目,在执行时输入当前线程及应用程序域的信息,最后生成Example.exe的可执行程序。

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

然后再新建一个ConsoleApplication项目,在此项目中新一个AppDomain对象,在新的AppDomain中通过ExecuteAssembly方法执行Example.exe程序。

C#
        static void Main(string[] args)
         {             //当前应用程序域信息
             Console.WriteLine("CurrentAppDomain start!");
             ShowMessage();             
             //建立新的应用程序域对象
             AppDomain newAppDomain = AppDomain.CreateDomain("newAppDomain");             //在新的应用程序域中执行Example.exe
             newAppDomain.ExecuteAssembly("Example.exe");
 
             AppDomain.Unload(newAppDomain);
             Console.ReadKey();
         } 
         public static void ShowMessage()
         {             var message = string.Format("  CurrentThreadID is:{0}\tAppDomainID is:{1}",
                 Thread.CurrentThread.ManagedThreadId, AppDomain.CurrentDomain.Id);
             Console.WriteLine(message);
         }



可见,ID等于9的线程在不同时间内分别运行于AppDomain 1与AppDomain 2当中。

 

4.3 跨上下文的线程

线程既然能够跨越AppDomain的边界,当然也能跨越不同的上下文。
下面这个例子中,线程将同时运行在默认上下文与提供安全线程的上下文中。

C#
class Program
      {
          [Synchronization]
          public class ContextBound : ContextBoundObject          {
              public void Test()
              {
                  ShowMessage();
              }
         }
 
         static void Main(string[] args)
         {
             //当前应用程序域信息
             Console.WriteLine("CurrentAppDomain start!");
             ShowMessage();
 
             //在上下文绑定对象中运行线程
             ContextBound contextBound = new ContextBound();
             contextBound.Test();
             Console.ReadKey();
         }
 
         public static void ShowMessage()
         {
             var message = string.Format("  CurrentThreadID is:{0}\tContextID is:{1}",
                  Thread.CurrentThread.ManagedThreadId, Thread.CurrentContext.ContextID);
             Console.WriteLine(message);
         }
    }

运行结果

image.png

 

本篇总结

进程(Process)、线程(Thread)、应用程序域(AppDomain)、上下文 (Context)的关系如图5.0,一个进程内可以包括多个应用程序域,也有包括多个线程,线程也可以穿梭于多个应用程序域当中。但在同一个时刻,线程 只会处于一个应用程序域内。线程也能穿梭于多个上下文当中,进行对象的调用。

虽然进程、应用程序域与上下文在平常的开发中并非经常用到,但深入地了解三者的关系,熟悉其操作方式对合理利用系统的资源,提高系统的效率是非常有意义的。
尤其是三者与线程之间的关系尤为重要,特别是在一个多线程系统中,如果不能理清其关系而盲目使用多线程,容易造成资源抢占与死锁之类的错误。


#转载请注明出处 www.skcircle.com 《少有人走的路》勇哥的工业自动化技术网站。


扫描二维码推送至手机访问。

版权声明:本文由7点博客发布,如需转载请注明出处。

本文链接:http://6dot.cn/?id=57

标签: .NET.NET框架
分享给朋友:

“细说进程、应用程序域与上下文之间的关系(四)——进程应用程序域与线程的关系” 的相关文章

C# 控件闪烁问题的解决

C# 控件闪烁问题的解决

说一下解决C#下控件闪烁的几个问题,如下:  listview和datagridview显示数据闪烁 自定义控件的显示闪烁listbox滚动条拖动闪烁面板中控件过多的闪烁propertyGrid点击和修改项目缓慢的问题richtextbox控件的刷新显示问题此类问题对于界面复杂规...

C# Modelbus crc16计算校验和程序

C# Modelbus crc16计算校验和程序

我们手里一个无刷电机,采用485的modelbus crc16协议来控制。因此需要一个计算校验和的工具。源码:C#using System;using System.Collections.Generic;using System.ComponentModel;usin...

C# tableLayoutPanel动态加载控件闪烁的解决方案

C# tableLayoutPanel动态加载控件闪烁的解决方案

WinForm加载多个自定义控件时,会出现很严重的闪烁问题,很卡,一块一块的加载(像打开网页时,网络很卡的那种感觉)简直没法忍受。在网上搜索了好久,网上大部分的方法是一下4种,但是都不能有效的解决问题。  1.将DoubleBuffered 设置 true,用双缓存处理Form界面内容加载,可以提高...

c#——表达式树在LINQ动态查询

c#——表达式树在LINQ动态查询

一般如果逻辑比较简单,只是存在有的情况多一个查询条件,有的情况不需要添加该查询条件简单方式这样操作就可以了C#public IQueryable<FileImport> DynamicChainedSyntax (IQueryable<FileImport&g...

C# await、UI和死锁的问题

C# await、UI和死锁的问题

开发人员对Asnync 异步机制的兴趣程度很高。当然,任何新技术都必然会出现一些小问题。我现在多次看到的一个问题是开发人员通过阻止他们的 UI 线程意外地使他们的应用程序死锁,所以我认为花一些时间来探索这种情况的常见原因以及如何避免这种困境是值得的。就其核心而言,新的异步语言功能旨在恢复开发人员编写...

如何在C#中调试LINQ查询

如何在C#中调试LINQ查询

在C#中我最喜欢的特性就是LINQ。使用LINQ, 我们可以获得一种易于编写和理解的简洁语法,而不是单调的foreach循环,它可以让你的代码更加美观。但是LINQ也有不好的地方,就是调试起来非常难。我们无法知道查询中到底发生了什么。我们可以看到输入值和输出值,但是仅此而已。当代码出现问题的时候,我...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。