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

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 に答える
1

作成中のドメインで型を参照している場合 ( のようにtypeof(OposHardwareManager))、アセンブリはそのドメインにも読み込まれます。こうなると、ドメインの境界を「上向き」に越えてしまうタイプがあるため、作成されたドメインをアンロードできません。

含まれているアセンブリを参照せず、OposHardwareManager代わりに完全修飾名で作成することをお勧めします。これには、いくつかのリファクタリングが含まれる場合があります。

于 2013-03-20T11:00:16.933 に答える