3

自己ホスト型の WCF サービスがあり、次の問題があります: サービスのインスタンスを作成してから 15 分後、操作コントラクト メソッドで TryEnter 呼び出しが常に false を返しますが、Monitor を介した同期も使用する Main 関数で TryEnter 呼び出しを行います。クラス、true を返します。

アプリとバグの説明は次のとおりです。 Windows XP SP2 の Visual Studio 2008 (C#) でセルフホステッド WCF サービスを開発しています。ホストの ServiceHost インスタンスは、Main 関数の開始時に作成されます。Main 関数は while (true) ループを実行し、その間に定期的な読み取り、書き込み、メンテナンスなどを実行します。ワーカー スレッドのコンテナーとして機能するオブジェクトの静的コレクション (時間の経過とともに追加または削除できます) があります。これらのスレッドには、Main 関数によって要求された定期的な作業を実行するスレッドもあれば、リモート デバイスへのオンデマンドの読み取りと書き込みを実行するスレッドもあります。Monitor クラス (TryEnter および Exit メソッド) を使用して、これらのオブジェクトに対して同期ロックが行われます。これらのオブジェクトには、同じ関数を使用するサービス コントラクト メソッド (サービス) からもアクセスできます。同期は、Main 関数とサービス メソッドの間で行われます。サービスのインスタンスが作成されると、設計されたパフォーマンスで正確に 15 分間実行されます。その後、サービスから行われるすべての TryEnter(obj, timeout) 呼び出しは、指定されたタイムアウトの期限が切れた後に false を返します。ただし、これは Main 関数で行われる TryEnter 呼び出しには影響しません。つまり、常に true を返します。サービス調整属性 maxConcurrentCalls="1" と組み合わせて、InstanceContextMode、ConcurrencyMode の設定を変更しようとしました。maxConcurrentSessions="5" であり、すべての構成で同じ効果が得られました。ホストアプリを再起動すると、サービスは再び応答しますが、アプリの実行中にホストを強制的に閉じて再度開くと、応答しなくなります (サービスインスタンスはメモリに残ります)。呼び出しがサービス インスタンスに到達しない場合のように、サービスが利用できない場合ではありません。メソッドが呼び出され、メソッドのクリティカル セクションに先行する TryEnter 呼び出しでその実行が行われ、TryEnter はタイムアウト (15 秒) 後に false を返します。TryEnter と Exit の組み合わせを確認し、二重に確認しました。クリティカル セクションが終了すると、メソッドは常にロックを解放します。ロックを使用しないその他のコントラクト操作または問題のオブジェクトは、15 分間の期間が終了した後でも正常に機能します。TryEnter と Exit の組み合わせを確認し、二重に確認しました。クリティカル セクションが終了すると、メソッドは常にロックを解放します。ロックを使用しないその他のコントラクト操作または問題のオブジェクトは、15 分間の期間が終了した後でも正常に機能します。TryEnter と Exit の組み合わせを確認し、二重に確認しました。クリティカル セクションが終了すると、メソッドは常にロックを解放します。ロックを使用しないその他のコントラクト操作または問題のオブジェクトは、15 分間の期間が終了した後でも正常に機能します。

よろしくお願いします。ハッピーホリデー!

4

1 に答える 1

3

Monitor再入可能であるため、Mainメソッドのスレッドがロックの解放に失敗したようです。したがって、ロックを要求すると ( TryEnter)、ロックを取得します (カウンターをもう1 つ増やします)。

他のすべてのスレッドは拒否されます。ロックが取得および保持される場所をデバッグする必要があります。

TryEnter と Exit の組み合わせを確認し、再確認しました。クリティカル セクションが終了すると、メソッドは常にロックを解放します。

申し訳ありませんが、トレブルチェックを行うと思います。特に、 とは異なりlockTryEnter特別な例外処理はありません。コードは次のようになります。

if(Monitor.TryEnter(lockObj, timeout)) {
    try {
        ...
    } finally {
        Monitor.Exit(lockObj);
    }
}

また、正しいオブジェクトのロックを解除できないため、コードで再署名しないようにしてください。lockObj

(またはフラグを使用して同様に、特に新しいオーバーロードがある.NET 4.0Enterなどで)

于 2009-12-30T11:48:18.613 に答える