卸载AppDomain动态调用DLL异步线程执行失败
应用场景
动态调用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异步线程执行失败的更多相关文章
- C#程序实现动态调用DLL的研究(转)
摘 要:在<csdn开发高手>2004年第03期中的<化功大法——将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资 ...
- C#程序实现动态调用DLL的研究[转]
摘 要: 在< csdn 开发高手> 2004 年第 03 期中的<化功大法——将 DLL 嵌入 EXE >一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在 ...
- C#程序实现动态调用DLL的研究
摘 要:在<csdn开发高手>2004年第03期中的<化功大法——将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资 ...
- 【VB技巧】VB静态调用与动态调用dll详解
本文“[VB技巧]VB静态调用与动态调用dll详解”,来自:Nuclear'Atk 网络安全研究中心,本文地址:http://lcx.cc/?i=489,转载请注明作者及出处! [[请注意]]:在以下 ...
- 动态调用DLL函数有时正常,有时报Access violation的异常
动态调用DLL函数有时正常,有时报Access violation的异常 typedef int (add *)(int a,int b); void test() { hInst=LoadL ...
- 利用C#的反射机制动态调用DLL类库
最近由于业务要求,需要动态调用DLL类库,所以研究了一下,感觉还好也不太难,今天就把自己理解的写了一个小例子(已经通过VS2005跑通),供大家一起研究和探讨,有理解不当的地方还请高手们多多指正,谢谢 ...
- VC动态调用DLL
1. //函数指针声明 typedef int (_stdcall MYDLLFUN)(char* _pcOut, /*INOUT*/int *_piOutBufLen, char* _pcIn, i ...
- C#中动态调用DLL动态链接库
其中要使用两个未公开的Win32 API函数来存取控制台窗口,这就需要使用动态调用的方法,动态调用中使用的Windows API函数主要有三个,即:Loadlibrary,GetProcAddress ...
- C#中动态调用DLL动态链接库(转)
本来是想实现控制台程序运行时自动全屏,但是只找到VC下的实现方法(http://www.vckbase.com/bbs/prime/viewprime.asp?id=347). 其中要使用两个未公开的 ...
随机推荐
- HDU 5410 CRB and His Birthday ——(完全背包变形)
对于每个物品,如果购买,价值为A[i]*x+B[i]的背包问题. 先写了一发是WA的= =.代码如下: #include <stdio.h> #include <algorithm& ...
- Android Studio启动模拟器
创建模拟器时出现vt x is disabled in bios 出现错误提示:"Intel HAXM is required to run this AVD,VT-x is disable ...
- nullcon HackIM 2016 -- Crypto Question 5
Now you are one step away from knowing who is that WARRIOR. The Fighter who will decide the fate of ...
- [python] ORM 第一次注释
不懂的东西还太多,就当是自己监督自己吧 #!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = 'Michael Liao' impor ...
- 安装Linux系统Fedora 23
搭建了一个Linux(Fedora 23)环境,用于学习.实验. [TOC] 1 安装Fedora 以前一直只会光盘安装,刻录了好多个版本的distros,用完即弃在一旁.很浪费. 此次学会了在Lin ...
- myeclipse 控制台打印空指针 ,黏贴控制台sql到plsql有结果集,异常处理
信用公司框架,不够熟悉. 在完成嗲点登录后,写动态页面是遇到,了问题:myeclipse 控制台打印空指针 ,黏贴控制台sql到plsql有结果集,异常处理. 最后大神给看,在接口实现重写的方法里返回 ...
- MVC4 本地正常运行,发布到IIS7->403 - 禁止访问: 访问被拒绝。
代码编写完成,计划发布一个版本测试,没想到发布到IIS7 竟然报错“403-禁止访问”.还真第一次遇到这种问题..... 折腾了半天,终于解决. 1.提示报错403: 禁止访问: 访问被拒绝.您无权使 ...
- 支付宝App支付签名和验签
代码: using CMS.Utility.ReturnResult; using OAuthWebAPI.Package; using Common; using System; using Sys ...
- iOS设置导航栏标题
方法一:在UIViewController中设置self.title. 方法二:设置self.navigationItem.titleView.
- agsXMPP参考代码
agsXMPP 1.删除好友 XmppCon.RosterManager.RemoveRosterItem(node.RosterItem.Jid); 2.注销用户 void userConn_OnL ...