2

我正在使用 .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;
    }
}

有任何想法吗?

4

3 回答 3

1

如果您在创建域中引用一个类型(就像您使用 一样typeof(OposHardwareManager)),程序集也将加载到该域中。发生这种情况时,iow 类型“向上”越过域边界,创建的域将无法卸载。

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

于 2013-03-20T11:00:16.933 回答
1

AppDomain.Unload的文档中指出:

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

这可能是你的情况。查看PosDevice有关如何正确释放资源的文档。

另请注意,由在新 AppDomain 中创建的线程引发的未处理异常将使您的整个应用程序崩溃。在AppDomain.UnhandledException Event的文档中指出:

在 .NET Framework 版本 1.0 和 1.1 中,发生在主应用程序线程以外的线程中的未处理异常会被运行时捕获,因此不会导致应用程序终止。因此,可能会在应用程序终止的情况下引发 UnhandledException 事件。从 .NET Framework 2.0 版开始,删除了对子线程中未处理异常的支持,因为这种静默故障的累积影响包括性能下降、数据损坏和锁定,所有这些都难以调试。

于 2013-03-21T09:41:37.423 回答
0

不确定这会有所帮助,但我在 Win 7 和 XP 上发现了同样的错误。在应用程序退出期间,应用程序崩溃并引发错误。但故障来自报告查看器,因此在卸载表单时请确保致电

报告查看器.Reset();

于 2015-04-24T09:47:01.003 回答