相关疑难解决方法(0)

如何使用C#正确卸载AppDomain?

我有一个应用程序加载我无法控制的外部程序集(类似于其他人创建和开发主应用程序使用的程序集的插件模型).它通过为这些程序集创建新的AppDomain来加载它们,然后在使用程序集完成后,主AppDomain将卸载它们.

目前,它简单地卸载这些程序集

try
{
    AppDomain.Unload(otherAssemblyDomain);
}
catch(Exception exception)
{
    // log exception
}
Run Code Online (Sandbox Code Playgroud)

但是,有时会在卸载过程中抛出异常CannotUnloadAppDomainException.根据我的理解,这是可以预料到的,因为由于非托管代码仍在执行或线程在finally块中的情况,子域AppDomains中的线程无法强制中止:

当线程调用Unload时,目标域将标记为卸载.专用线程尝试卸载域,并且域中的所有线程都将中止.如果线程没有中止,例如因为它正在执行非托管代码,或者因为它正在执行finally块,那么在一段时间之后,在最初调用Unload的线程中抛出CannotUnloadAppDomainException.如果最终无法中止的线程结束,则不会卸载目标域.因此,在.NET Framework 2.0版域中不保证卸载,因为它可能无法终止执行线程.

我担心的是,如果没有加载程序集,那么它可能会导致内存泄漏.如果出现上述异常,可能的解决方案是杀死主应用程序进程,但我宁愿避免这种激烈的行为.

我还在考虑重复卸载电话以进行一些额外的尝试.也许像这样的约束循环:

try
{
    AppDomain.Unload(otherAssemblyDomain);
}
catch (CannotUnloadAppDomainException exception)
{
    // log exception
    var i = 0;
    while (i < 3)   // quit after three tries
    {
        Thread.Sleep(3000);     // wait a few secs before trying again...
        try
        {
            AppDomain.Unload(otherAssemblyDomain);
        }
        catch (Exception)
        {
            // log exception
            i++;
            continue;
        }
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

这有意义吗?我是否应该再次尝试卸载呢?我应该尝试一次继续前进吗?还有什么我应该做的吗?此外,如果线程仍在运行,是否可以从主AppDomain完成控制外部程序集的任何事情(请记住其他人正在编写并运行此外部代码)? …

.net c# appdomain

22
推荐指数
1
解决办法
2万
查看次数

标签 统计

.net ×1

appdomain ×1

c# ×1