複数のAppDomainを持つアプリケーションでのMicrosoft.Win32.SystemEventsの機能

昔々、appdomainを作成し、その中のTopshelfに基づくサービスを起動するコンソールアプリケーションがありました。 しかし、一度バグが発生すると、Ctrl-Cを押しても作業は終了しませんでしたが、シャットダウンコマンドを受信し、この状態でフリーズしたと報告しました。 簡単な分析では、ドメインのアンロードでハングすることが示されましたが、奇妙なことに、 CannotUnloadAppDomainException



例外はスローされませんでした。



さらに、特定のタスクを実行した後にのみアプリケーションを閉じるとアプリケーションがフリーズし、ドメインをアンロードする前にいくつかの「余分な」スレッドが存在することに注意しました。 名前から推測できるように、 SystemEvents



ことがSystemEvents



System.Drawing.SolidBrush



を使用すると、ハンドラーがSystemEvents.UserPreferenceChanging



に追加されSystemEvents.UserPreferenceChanging



が、これは別個のappdomainであるため、タイプは再度初期化され、「。NET SystemEvents」という名前で別のスレッドが作成されます。

アプリケーションを閉じると、 SystemEvents.Dispose()



が呼び出され、コンソールハンドラーUnsafeNativeMethods.SetConsoleCtrlHandler(consoleHandler, 0)



アプリケーションがフリーズします。 コンソールハンドラーの削除に関する問題についていくつか言及しましたが、すべての解決策SystemEvents.Shutdown()



をReflection経由で呼び出すことになりましたが、それは役に立たず、役に立たないはずなので、Dispose()を呼び出します。

次に、2番目のSystemEventsストリームの作成を何らかの方法で回避する必要があると判断し、 SystemEvents.EnsureSystemEvents(bool requireHandle, bool throwOnRefusal)



メソッドSystemEvents.EnsureSystemEvents(bool requireHandle, bool throwOnRefusal)



抜け穴が見つかりました。



 if (Thread.GetDomain().GetData(".appDomain") != null) { if (throwOnRefusal) { throw new InvalidOperationException(SR.GetString(SR.ErrorSystemEventsNotSupported)); } return; } //   SystemEvents
      
      





私の場合、このメソッドはthrowOnRefusal = falseで呼び出されたため、 domain.SetData(".appDomain", new object())



を追加すると、別のSystemEventsスレッドの作成を回避し、コンソールハンドラーが削除されるとフリーズし、アプリケーションは正常に動作を終了します。

「.appDomain」プロパティの確認に依存するコードの場合、副作用が発生する可能性があります。アプリケーションがasp.netとしてカウントされる場合があります))この設定が引き起こす問題を誰かが知っている場合、または問題に対するより安全で適切な解決策を知っている場合、共有してください。



All Articles