C#ロックおよびコード分析警告CA2002
-
06-07-2019 - |
質問
アプリケーションには、同期プロセスを開始するフォームがあり、いくつかの理由から、一度に1つの同期のみを実行できるようにしたいと考えています。したがって、同期が進行中かどうかを示す静的ブールフィールドをフォームに追加し、最初のスレッドが同期を開始できるように設定されていない場合はこのフィールドをtrueに設定するロックを追加しましたが、それは他のすべてのスレッドを実行しているときに開始しようとすると終了します。
私のコードは次のようなものです:
internal partial class SynchronizationForm : Form
{
private static volatile bool workInProgress;
private void SynchronizationForm_Shown(object sender, EventArgs e)
{
lock (typeof(SynchronizationForm))
{
if (!workInProgress)
{
workInProgress = true;
}
else
{
this.Close();
}
}
}
}
これはうまく機能していますが、プロジェクトでコード分析を実行すると、次の警告メッセージが表示されます。
CA2002:Microsoft.Reliability: 'SynchronizationForm.SynchronizationForm_Shown(object、EventArgs)'は、タイプ 'Type'の参照をロックします。これを、強いアイデンティティを持つオブジェクトに対するロックに置き換えます。
私のコードの何が問題なのか、どのように改善すれば警告が消えるのか、誰にでも説明できますか。オブジェクトに強いアイデンティティがあることはどういう意味ですか?
解決
間違っているのは、コードからどこからでもアクセスできるパブリック( typeof(SynchronizationForm)
)をロックしていることです。一般に、プライベートな静的オブジェクトでのみロックすることをお勧めします:
private static object _syncRoot = new object();
...
lock (_syncRoot)
{
}
これにより、ロックを所有できるのは SynchronizationForm
のみであることが保証されます。
他のヒント
オブジェクトは、アプリケーションドメインの境界を越えて直接アクセスできる場合、弱いアイデンティティを持つと言われます。弱いIDを持つオブジェクトのロックを取得しようとするスレッドは、同じオブジェクトをロックする別のアプリケーションドメインの2番目のスレッドによってブロックされる可能性があります。
別のAppDomainがどのロックを使用するかを必ずしも予測できるわけではないため、このようなロックはマーシャリングする必要があり、その後高価になるため、このルールは理にかなっています。
問題は、typeof(SynchronizationForm)がプライベートロックオブジェクトではないことです。つまり、他のコードがそれを使用してロックオンし、デッドロックが発生する可能性があります。たとえば、他のコードがこれを行った場合:
var form = new SynchronizationForm();
lock(typeof(SynchronizationForm))
{
form.SomeMethodThatCausesSynchronizationForm_ShownToBeCalled();
}
その後、デッドロックが発生します。代わりに、SynchronizationFormクラスのプライベートロックオブジェクトを削除し、代わりにロックする必要があります。
クラスの
System.Type
オブジェクトは、クラスの静的メソッドの相互排他ロックとして便利に使用できます。
出典: http://msdn.microsoft。 com / en-us / library / aa664735(VS.71).aspx
Dougの答えに追加するのは、インスタンスメソッドで使用される静的メソッドでのみ使用されるロックメカニズムです。