私が今知っていることの簡単な要約
作成してEventWaitHandle閉じた があります。この ctorで再作成しようとすると、「パスへのアクセス ... が拒否されました」という例外がスローされます。この例外はまれであり、ほとんどの場合、問題なく再作成されますEventWaitHandle。以下に(私が)投稿した回答を使用するEventWaitHandle.OpenExistingと、例外がスローされた場合でも正常に呼び出して続行できますが、ctor はEventWaitHandle私のためにこれを行うべきでしたよね? それがout パラメータ,createdNewの目的ではありませんか?
最初の質問
同じサーバー上に次のアーキテクチャ、Windows サービス、および Web サービスがあります。Web サービスは、Windows サービスが待機している待機ハンドルを開いて設定することにより、作業を行う必要があることを Windows サービスに伝えます。
通常、すべてに問題はなく、問題が発生することなく Windows サービスを開始/停止できます。ただし、Web サービスを停止してから再起動すると、待機ハンドルを完全に作成できず、アーキテクチャ全体が壊れてしまうことがあります。
特に、何がイベント待機ハンドルを壊しているのかを突き止めて停止する必要があります。待機ハンドルが「壊れた」場合、ウィンドウが再び適切に機能する前にウィンドウを再起動する必要がありますが、これは明らかに理想的ではありません。
更新: スローされた例外と問題のログ
問題を引き起こすことを期待して、Web サービスが動作している間に Windows サービスを再起動しました。一部のクラス名は、企業の匿名性のために検閲されています
12:00:41,250 [7] - Stopping execution due to a ThreadAbortException
System.Threading.ThreadAbortException: Thread was being aborted.
at System.Threading.Thread.SleepInternal(Int32 millisecondsTimeout)
at OurCompany.OurProduct.MyClass.MyClassCore.MonitorRequests()
12:00:41,328 [7] - Closing Event Wait Handle
12:00:41,328 [7] - Finally block reached
12:00:42,781 [6] - Application Start
12:00:43,031 [6] - Creating EventWaitHandle: Global\OurCompany.OurProduct.MyClass.EventWaitHandle
12:00:43,031 [6] - Creating EventWaitHandle with the security entity name of : Everyone
12:00:43,078 [6] - Unhandled Exception
System.UnauthorizedAccessException: Access to the path 'Global\OurCompany.OurProduct.MyClass.EventWaitHandle' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.Threading.EventWaitHandle..ctor(Boolean initialState, EventResetMode mode, String name, Boolean& createdNew, EventWaitHandleSecurity eventSecurity)
at OurCompany.OurProduct.MyClassLibrary.EventWaitHandleFactory.GetNewWaitHandle(String handleName, String securityEntityName, Boolean& created)
at OurCompany.OurProduct.MyClassLibrary.EventWaitHandleFactory.GetNewEventWaitHandle()
at OurCompany.OurProduct.MyClass.MyClassCore..ctor()
大まかなタイムライン:
11:53:09,937: Web サービスの最後のスレッドが既存の待機ハンドルを開き、その作業を完了しました (クライアントとの接続が終了した場合と同様)。
12:00:30,234: Web サービスは新しい接続を取得しますが、まだ待機ハンドルを使用していません。この接続のスレッド ID は、11:53 の最後の接続のスレッド ID と同じです。
12:00:41,250: Windows サービスが停止します
12:00:42,781: Windows サービスが起動します
12:00:43,078: Windows サービスのクラッシュが終了しました
12:00:50,234: Web サービスは実際に待機ハンドル呼び出し Set() を開くことができましたが、例外がスローされることはありませんでした。
12:02:00,000: Windows サービスを再起動しようとしましたが、同じ例外が発生しました
12:36:57,328: 任意に 36 分間待った後、システムを完全に再起動することなく、Windows サービスを開始することができました。
Windows サービス コード
初期化:
// I ran into security issues so I open the global EWH
// and grant access to Everyone
var ewhSecurity = new EventWaitHandleSecurity();
ewhSecurity.AddAccessRule(
new EventWaitHandleAccessRule(
"Everyone",
EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify,
AccessControlType.Allow));
this.ewh = new EventWaitHandle(
false,
EventResetMode.AutoReset,
@"Global\OurCompany.OurProduct.MyClass.EventWaitHandle",
out created,
ewhSecurity);
// the variable "created" is logged
利用:
// wait until the web service tells us to loop again
this.ewh.WaitOne();
廃棄/閉鎖:
try
{
while (true)
{
// entire service logic here
}
}
catch (Exception e)
{
// should this be in a finally, instead?
if (this.ewh != null)
{
this.ewh.Close();
}
}
Web サービス コード
初期化:
// NOTE: the wait handle is a member variable on the web service
this.existing_ewh = EventWaitHandle.OpenExisting(
@"Global\OurCompany.OurProduct.MyClass.EventWaitHandle");
利用:
// wake up the windows service
this.existing_ewh.Set();
は Web サービスのメンバー変数であるためEventWaitHandle、具体的に閉じるコードはありません。実際、EventWaitHandleオン ザ Web サービスと対話する唯一のコードは上に掲載されています。
振り返ってみるとClose()、catchブロック内にある をブロック内に置くべきだったのかもしれませんfinally。おそらく Web サービスに対しても同じことを行うべきだったのですが、それが必要だとは思いませんでした。
いずれにせよ、私が特に間違ったことをしているかどうかは誰にもわかりますか? close ステートメントを finally ブロック内に配置することは非常に重要ですか? Web サービスClose()のを手動で制御する必要がありますか?existing_ewh
また、これはやや複雑な問題であることは承知しています。追加情報が必要な場合はお知らせください。詳しく監視し、必要な情報や説明を追加します。
参考資料