应用场景

动态调用DLL中的类,执行类的方法实现业务插件功能

使用Assembly 来实现

但是会出现逻辑线程数异常的问题

使用AppDomain 实现动态调用,并卸载。

发现问题某个插件中开启异步线程,会抛线程终止的异常。

百度查到把线程执行代码放到finally块中

AppDomain很出色的一个能力就是它允许卸载。卸载AppDomain会导致CLR卸载AppDomain中的所有程序集,还会释放AppDomain的Loader堆。为了卸载一个AppDomain,可以调用AppDomain的静态方法Unload。这导致了CLR执行一些列操作来得体地卸载指定AppDomain。

1.         CLR挂起进程中执行过托管代码的所有线程

2.         CLR检查所有线程栈,查看哪些线程正在执行要卸载的那个AppDomain中的代码,或者哪些线程会在某个时刻返回至要卸载的那个AppDomain。在任何一个栈上,如果准备卸载的AppDomain,CLR都会强迫对应的线程抛出一个ThreadAbortException异常(同时恢复线程的执行)。这将导致线程展开(unwind),在展开的过程中执行遇到的所有finally块中的内容,以执行资源清理代码。如果没有代码捕捉ThreadAbortException,它最终会成为一个未处理的异常,CLR会“吞噬”这个异常,线程会终止,但进程可以继续运行。这一点是非常特别的,因为对于其他所有未处理的异常,CLR都会终止进程。

重要提示:如果一个线程当前正在finally块、catch块、类构造器、临界执行区(critical execution region)域或非托管代码中执行,那么CLR不会立即终止该线程。否则,资源清理代码、错误恢复代码、类型初始化代码、关键代码或者其他任何CLR不了解的代码都无法完成,导致应用程序的行为变得无法预测,甚至可能造成安全漏洞。线程在终止时,会等待这些代码块执行完毕。然后当代码块结束时,CLR再强制线程抛出一个ThreadAbortException

临界区是指线程终止或未处理异常的影响可能不限于当前任务的区域。相反,非临界区中的终止或失败只对出现错误的任务有影响。

3.         当上一步发现的所有线程都离开AppDomain后,CLR遍历堆,为引用了“已卸载的AppDomain创建的对象”的每一个代理都设置一个标志(flag)。这些代理对象现在知道它们引用的真实对象已经不在了。如果任何代码在一个无效的代理对象上调用一个方法,该方法会抛出一个AppDomainUnloadedException

4.         CLR强制垃圾回收,对现已卸载AppDomain创建的任何对象占用的内存进行回收。这些对象的Finalize方法被调用(如果存在Finalize方法),使对象有机会彻底清理它们占用的资源

5.         CLR恢复剩余所有线程的执行。调用AppDomain.Unload方法的线程将继续执行,对AppDomain.Unload的调用是同步进行的

在前面的例子中,所有工作都用一个线程来做。因此,任何时候只要调用AppDomain.Unload都不可能有另一个线程在要卸载的AppDomain中。因此,CLR不必抛出任何ThreadAbortException异常。

顺便说一句,当一个线程调用AppDomain.Unload方法时,针对要卸载的AppDomain中的线程,CLR会给它们10秒钟的时间离开。10秒后,如果调用AppDomain.Unload方法的线程还没有返回,CLR将抛出一个CannotUnloadAppDomainException异常,AppDomain将来可能会也可能不会卸载。

注意:如果调用AppDomain.Unload方法的线程不巧在要卸载的AppDomain中,CLR会创建另一个线程来尝试卸载AppDomain。第一个线程被强制抛出一个ThreadAbortException兵展开。新建的线程将等待AppDomain卸载,然后新线程会终止。如果AppDomain卸载失败,新线程将处理CannotUnloadAppDomainException异常。但是,由于我们没有写供这个新线程执行的代码,所以无法捕获这个异常。

卸载AppDomain动态调用DLL异步线程执行失败的更多相关文章

  1. C#程序实现动态调用DLL的研究(转)

    摘 要:在<csdn开发高手>2004年第03期中的<化功大法——将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资 ...

  2. C#程序实现动态调用DLL的研究[转]

    摘   要: 在< csdn 开发高手> 2004 年第 03 期中的<化功大法——将 DLL 嵌入 EXE >一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在 ...

  3. C#程序实现动态调用DLL的研究

    摘 要:在<csdn开发高手>2004年第03期中的<化功大法——将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资 ...

  4. 【VB技巧】VB静态调用与动态调用dll详解

    本文“[VB技巧]VB静态调用与动态调用dll详解”,来自:Nuclear'Atk 网络安全研究中心,本文地址:http://lcx.cc/?i=489,转载请注明作者及出处! [[请注意]]:在以下 ...

  5. 动态调用DLL函数有时正常,有时报Access violation的异常

    动态调用DLL函数有时正常,有时报Access violation的异常 typedef int (add *)(int a,int b); void test() {     hInst=LoadL ...

  6. 利用C#的反射机制动态调用DLL类库

    最近由于业务要求,需要动态调用DLL类库,所以研究了一下,感觉还好也不太难,今天就把自己理解的写了一个小例子(已经通过VS2005跑通),供大家一起研究和探讨,有理解不当的地方还请高手们多多指正,谢谢 ...

  7. VC动态调用DLL

    1. //函数指针声明 typedef int (_stdcall MYDLLFUN)(char* _pcOut, /*INOUT*/int *_piOutBufLen, char* _pcIn, i ...

  8. C#中动态调用DLL动态链接库

    其中要使用两个未公开的Win32 API函数来存取控制台窗口,这就需要使用动态调用的方法,动态调用中使用的Windows API函数主要有三个,即:Loadlibrary,GetProcAddress ...

  9. C#中动态调用DLL动态链接库(转)

    本来是想实现控制台程序运行时自动全屏,但是只找到VC下的实现方法(http://www.vckbase.com/bbs/prime/viewprime.asp?id=347). 其中要使用两个未公开的 ...

随机推荐

  1. 查询阻塞的sql

    WITH ProcessCTE(blocked) AS ( SELECT blocked FROM sys.sysprocesses WHERE blocked>0 union SELECT s ...

  2. linux下redis的安装与部署及基础命令

    <1>下载安装文件:redis-3.2.5.tar.gz 放在opt目录下 <2> tar -zxvf redis-3.2.5.tar.gz,备份redis.conf到自己的目 ...

  3. Tomcat启动时项目重复加载,导致资源初始化两次的问题

    http://blog.csdn.net/testcs_dn/article/details/38855641

  4. JS实现的随机显示图片

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...

  5. Angularjs学习笔记(一)

    大部分传统的模板系统,对模板的渲染是个线性单向的过程:模板或变量与模板混合在一起产生结果的标记集合.任何对模型的改变都需要通过模板的重新计算.但AngularJS有所不同,任何用户引发的视图的改变,都 ...

  6. 初学c# -- 学习笔记(五) winfrom无边框四周阴影

    刚用到这个功能,网上扯淡的东西太多了,都是2边阴影,还什么窗口叠加.ps作图啥的,什么玩意.还是老外实在,google找的,无边框窗体,四边透明阴影. public partial class For ...

  7. String类的常用判断方法使用练习

    选取了一些常用的判断方法进行了使用练习,后续跟新其他方法 package StringDemo; // String类的判断方法解析 // 1:boolean equals(); // 判断字符串是否 ...

  8. linux命令(8):cp 命令

    cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不管你是否使用-i参数.但是如果是 ...

  9. iOS启动页设置

    点击项目->TARGETS->App Icons and Launch Images->Launch Images Source->Use Asset Catalog...-& ...

  10. exit

    -------siwuxie095 三个退出命令: exit exit /b goto :eof 这三个命令都可以退出批处理,但之间有细微差别: (1)运行 GOTO :EOF 后,CMD返回并将等待 ...