卸载包含POS硬件的子AppDomain,导致CannotUnloadAppDomainException

本文关键字:AppDomain 导致 CannotUnloadAppDomainException 包含 POS 硬件 卸载 | 更新日期: 2023-09-27 18:04:55

我使用。net 4.0, POS.net 1.12,我在一个新的子AppDomain中创建了一个硬件类,这样任何未处理的异常都不会杀死我的父AppDomain。

我可以创建子AppDomain并对其进行调用。但是,如果我试图卸载AppDomain,我会得到异常"CannotUnloadAppDomainException"。

我已经搜索了这个问题,异常通常发生在线程不能被杀死的时候。我实际上没有在子类中创建任何新线程。

我设法查明了导致这个错误的代码段。如果我创建POS硬件类,它只创建POS对象,那就没问题了。但是,如果在任何硬件上调用方法"Open()",则在卸载时发生此异常。现在,在我尝试卸载之前,我关闭了所有硬件,并确保清理代码被击中,所以我不确定问题是什么。

下面是创建和卸载AppDomain的代码:
AppDomain hardwareDomain = AppDomain.CreateDomain("Hardware domain");
IHardwareManager hardwareManager =
        (IHardwareManager)hardwareDomain.CreateInstanceFromAndUnwrap(typeof(OposHardwareManager).Assembly.Location,
                                                                     typeof(OposHardwareManager).FullName);
hardwareManager.StartupHardware();
hardwareManager.CloseDownHardware();
hardwareManager = null;
// **** causes exception
AppDomain.Unload(hardwareDomain);

这里是硬件类:

public class OposHardwareManager : MarshalByRefObject, IHardwareManager
{
    private PosExplorer _posExplorer;
    private PosPrinter _printer;
    public void StartupHardware()
    {
        // create the hardware explorer
        this._posExplorer = new PosExplorer();
        // create and enable the printer
        DeviceInfo printerInfo = this._posExplorer.GetDevice(DeviceType.PosPrinter);
        PosDevice printerDevice = this._posExplorer.CreateInstance(printerInfo);
        this._printer = (PosPrinter)printerDevice;
        // ***** this line here, if run, causes the exception on unload 
        this._printer.Open();
        this._printer.Claim(2000);
        this._printer.DeviceEnabled = true;
    }
    public void CloseDownHardware()
    {
        this._printer.Release();
        this._printer.Close();
        this._printer = null;
        this._posExplorer = null;
    }
}

任何想法?

卸载包含POS硬件的子AppDomain,导致CannotUnloadAppDomainException

如果您在创建域中引用类型(就像您在typeof(OposHardwareManager)中所做的那样),则程序集也将加载到该域中。当这种情况发生时,低类型越过域边界'向上',创建的域无法卸载。

我建议您不要引用包含OposHardwareManager的程序集,而是简单地使用完整的限定名创建它。这可能涉及到一些重构。

在AppDomain文档中。卸载时注意到:

如果一个线程没有中止,例如因为它正在执行非托管代码,或者因为它正在执行finally块,然后after方法中抛出CannotUnloadAppDomainException异常一段时间最初调用Unload的线程

这可能就是你的情况。查看PosDevice的文档,了解如何正确释放资源。

还要注意,在新AppDomain中创建的线程抛出的未处理异常将导致整个应用程序崩溃。在AppDomain文档中。UnhandledException事件:

在。net框架1.0和1.1版本中,一个未处理的异常发生在主应用程序线程以外的线程中由运行时捕获,因此不会导致应用程序终止。因此,UnhandledException事件可能是在应用程序不终止的情况下引发。从。net开始框架2.0版,这是对child中未处理异常的支持线程被移除了,因为这样的累积效应是无声的故障包括性能下降、数据损坏和锁,所有这些都很难调试。

不确定这是否有帮助,但我在win7和XP上发现了同样的错误。在应用程序退出期间,应用程序崩溃并抛出错误。但是错误来自报表查看器所以当卸载表单时请确保调用

reportviewer.Reset ();