私のWebサービスは、このコードC#のWebサービスにおける時間のタイムアウト
lock(typeof MyWebServiceClass)
を持っていることをロックさて私は、サードパーティの不変コードを呼び出すと、それは戻ることはありません。ブーム! BAM!
私は今永遠にロックされ、私のウェブサイトはクラッシュします。
これは決して偉大な中で一度しか起こりません。
タイムアウトするロックを作成することはできますか? IEは5分間コードをロックしてロックを解除しますか?
私のWebサービスは、このコードC#のWebサービスにおける時間のタイムアウト
lock(typeof MyWebServiceClass)
を持っていることをロックさて私は、サードパーティの不変コードを呼び出すと、それは戻ることはありません。ブーム! BAM!
私は今永遠にロックされ、私のウェブサイトはクラッシュします。
これは決して偉大な中で一度しか起こりません。
タイムアウトするロックを作成することはできますか? IEは5分間コードをロックしてロックを解除しますか?
代わりのタイミングロックを作成します、私はあなたのサードパーティの要求を別のスレッド/タスクに入れて制限します。その後、スレッド(または.NET 4.0とTPLが利用可能な場合はタスク)を開始し、タイムアウトを指定して応答に参加します。結合がタイムアウトした場合は、スレッドをキャンセルします(または、TPLタスクのキャンセルトークンを呼び出します)。
タイムアウトするロックを作成することはできますか?
はい、この不快な状況は、しばしばdeadlockと呼ばれます。
通常ではなく、インスタンスフィールドやクラス自体にロックの静的なプライベートオブジェクトをロックすることをお勧めし:
private static object _syncRoot = new object();
、その後:
lock(_syncRoot) {
}
ロックで実行されている彼のコードを参照することは非常に、非常に長い時間を要し、時には戻ってこない... –
@James Michael Hare、はい、これにより、ロックするためにインスタンスフィールドを使用している場合、デッドロックに陥る可能性が大幅に増加します。 –
非常に真です。私は彼が型のインスタンスをロックするべきではないということに同意します。おそらく、もしデッドロックまたはロングリクエストの場合、もっと知っているロックをどこで使用していたかを知っていれば、いずれにしても、ロックオブジェクトをあなたが言ったようにプライベートインスタンスにする必要があります。 –
サードパーティAPIにキャンセルメカニズムがある場合は、それを使用します。
lock(typeof MyWebServiceClass)
{
if (ThirdPartyApiThatAcceptsTimeout(TimeSpan.FromMinutes(5)))
{
// The call was successful so proceed.
}
else
{
// The call timed out so bail out.
return;
}
}
ただし、このAPIにはキャンセルメカニズムがないと思われるため、この質問を提起しました。そうであれば、これは指数関数的に難しくなりました。
単純なアプローチは、API呼び出しを別のスレッドに延期することです。スレッドが適時に応答しない場合、スレッドは中断できます。
lock(typeof MyWebServiceClass)
{
var thread = new Thread(
() =>
{
ThirdPartyApiThatCouldBlockIndefinitely();
});
thread.Start();
if (thread.Join(TimeSpan.FromMinutes(5))
{
// The call was successful so proceed.
}
else
{
// The call timed out so bail out.
thread.Abort();
return;
}
}
これには多くの問題があります。まず、スレッドがアボート要求を受け入れる保証はありません。 2.0以降、CLRには、スレッドにアボートを挿入できる特別なルールがあります。アンマネージドコードの実行中にCLRがインジェクションを延期すると私は信じています。したがって、APIが管理されていない場合、アボートが機能しない可能性があります。また、スレッドはThreadAbortException
を捕まえて無視できるので、中止は任意です。第2に、アボートは非同期で注入できるため、アボートは危険です。これにより、共有状態の破損を防ぐことが非常に困難になります。そのためAppDomainは通常、中止後に終了します。
これを処理する最も安全な方法は、API呼び出しを別のプロセスに入れることです。 .NET Remoting、WCF、パイプなどのプロセス間通信プロトコルを使用して、データを転送する必要があります。これは、維持するのが本当に苦痛になります。ただし、呼び出し元のAppDomainを壊すリスクなしに、プロセスを安全に終了できるので、最も安全です。
この問題は本当に正しく解決するのが難しいので、私は本当にあなたに感銘を受けた。
コンピュータワールドのロックに5分間は長い時間です... –
*致命的な抱擁*(トリガーホラー音楽)に詰まっているような音 –
何が使用されますか?呼び出しコードはロックされたセクションに残ります。あなたはロックを取得するためのタイムアウトを使用し、そこからあなたの道をコードすることができます。 –