コールスタック内の以下のいずれのメソッドでもロックを使用しないでコード内の特定のメソッドが呼び出されたことを検出する方法はありますか?
目的は、障害のあるアプリケーションをデバッグして、特定のコードがスレッドセーフでないかどうかを調べることです。メソッドがロックなしで呼び出されたことの検出
答えて
これはAOP(アスペクト指向プログラミング)のまともな使用例のようです。 AOPの非常に基本的な要約は、コードを乾燥させ、モジュール化するためにクロスカットの問題を扱う方法だということです。アイデアは、各メソッドの開始時と終了時にログを追加するのではなく、オブジェクトのすべてのメソッド呼び出し(例:各呼び出しのログ)を行う場合、オブジェクトを継承してクラス外で行うことですその目的は泥ではない。
これはいくつかの方法で行うことができ、私は2つの例を挙げます。最初は手動です(これは素晴らしいことではありませんが、小さなキャセットの場合は非常に簡単に行うことができます)。
DoerにはDoとOtherという2つのメソッドがあるとします。あなたはそれを継承し、
public class Doer
{
public virtual void Do()
{
//do stuff.
}
public virtual void Other()
{
//do stuff.
}
}
public class AspectDoer : Doer
{
public override void Do()
{
LogCall("Do");
base.Do();
}
public override void Other()
{
LogCall("Other");
base.Other();
}
private void LogCall(string method)
{
//Record call
}
}
あなたが唯一のクラスを気が、すぐにあなたが多くのクラスのためにそれをしなければならない場合には実現不可能になった場合にこれは素晴らしいですを作ることができます。そのような場合は、CastleProxyライブラリのようなものを使用することをお勧めします。これは、任意のクラスをラップするためのプロキシを動的に生成するライブラリです。 IOCと組み合わせると、アプリケーション内のすべてのサービスを簡単にラップすることができます。
ここで、CastleProxyを使用しての簡単な例の主なポイントは使用ProxyGenerator.GenerateProxyているとメソッドの周りのものを行うためにIInterceptorsに渡すコール:今すぐ
[Test]
public void TestProxy()
{
var generator = new ProxyGenerator();
var proxy = generator.CreateClassProxy<Doer>(new LogInterceptor());
proxy.Do();
Assert.True(_wasCalled);
}
private static bool _wasCalled = false;
public class LogInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Log(invocation.Method.Name);
invocation.Proceed();
}
private void Log(string name)
{
_wasCalled = true;
}
}
、ログ部分を。私はあなたがロックレスであることを本当に必要としているかどうか確信していません。短いロックでは十分かもしれませんが、あなたが思うように進むことができます。
ロックフリーの操作をサポートするC#のツールはよくわかりませんが、この中で最も単純なのはInterlockedを使用して、メソッド内のインスタンスの数をいつでも増やすことです
[Test]
public void TestProxy()
{
var generator = new ProxyGenerator();
var proxy = generator.CreateClassProxy<Doer>(new LogInterceptor());
proxy.Do();
Assert.AreEqual(1, _totalDoCount);
}
private static int _currentDoCount = 0;
private static int _totalDoCount = 0;
public class LogInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
if (invocation.Method.Name == "Do")
{
var result = Interlocked.Increment(ref _currentDoCount);
Interlocked.Increment(ref _totalDoCount);
if(result > 1) throw new Exception("thread safe violation");
}
invocation.Proceed();
Interlocked.Decrement(ref _currentDoCount);
}
}
インターロックは、スレッドセーフな操作を行うために魔法のレジスタの魔法を使用しています(スワップの比較-AND-私は信じて、私は本当に知らない):このような何かを見て。単に「起こった」よりも多くの文脈が必要な場合。並行スタックまたは同時ロックを使用することができます。これらのキューはロックなしです(インターロックも使用します:https://msdn.microsoft.com/en-us/library/dd997305.aspx/)。私は、それらが発生した順序で要素を返すことを約束するかどうかを知るために十分に使用していないので、これらにタイムスタンプを含めることにします。
上記のように、あなたは自由な操作をロックする必要はありませんが、これは必要です。私はあなたの正確な問題を知らないので、これのどれかがあなたにとって完璧なものかどうかはわかりませんが、これに取り組むためのツールを提供する必要があります。
はい、 'Interlocked.Increment'は、アトミックのコンペ・アンド・スワップ操作を使用します。 – Georg
host the CLR yourselfとなり、IHostSyncManager::CreateMonitorEventメソッドを使用して取得したロックを追跡できます。あなたは、あなたのホストから、あなたのメソッドに、 "IsLockTaken()"という独自のメカニズムを公開する必要があります。その後、実際のコードであなたのメソッドから呼び出すことができます。
私はそれは可能だと思いますが、それはあなたが解決しようとしている問題からかなりの労力とほぼ確実に気を散らすでしょうが、間違いなく多くの楽しみです!
ここでデッドロックの検出に興味深い読み取りだhttps://blogs.msdn.microsoft.com/sqlclr/2006/07/25/deadlock-detection-in-sql-clr/
- 1. Ios:Delegeteメソッドが呼び出されない
- 2. UICollectionViewLayoutメソッドが呼び出されない
- 3. メソッドonHandleIntent()が呼び出されない
- 4. CellForRowAtIndexメソッドが呼び出されない
- 5. オーバーライドされたメソッドを呼び出すと、オーバーライドされた呼び出しメソッドのスーパークラス
- 6. 非アプリケーションアクティビティが呼び出されたときの検出
- 7. アプリケーションがバックグラウンドから呼び出されたときにメソッドを呼び出す
- 8. NHibernate:カスタムプロパティアクセサのGetメソッドとSetメソッドが呼び出されない
- 9. トランジェントエンドが呼び出されたときにjavascriptメソッドが呼び出されない
- 10. Android:onRestoreInstanceStateがスクリーンウェイクアップ(およびロック)後に呼び出されない
- 11. Spring AOP @AfterThrowing - メソッドの詳細を呼び出すメソッドの呼び出し(メソッドを呼び出さない)
- 12. Spring Kafka -Consumerが呼び出さないメソッドを呼び出す
- 13. なぜ、メソッド#アーリティが呼び出されたのですか?
- 14. struts2でメソッドのメソッドが呼び出されない
- 15. メソッドが呼び出されたときにCurret日付がアングルで呼び出される
- 16. "TypeError:if文(Python)でメソッドが呼び出されたときに 'str'オブジェクトが呼び出されません '
- 17. textFieldShouldBeginEditingが呼び出され、textFieldDidBeginEditingが呼び出されない
- 18. パラメータと異なるオブジェクトで呼び出された同じメソッド
- 19. Androidと同じメソッドが2回呼び出されました
- 20. なぜメタクラス__getattribute__が呼び出されたのですか?ここ
- 21. リセットを呼び出すことなく呼び出されたリセットイベント
- 22. メソッドがラムダで呼び出されたときにブレークポイントがヒットしない
- 23. メソッドの呼び出し元をトラッキングする[呼び出しによって呼び出された]
- 24. C#連続したラムダ呼び出しでラムダコンストラクタが呼び出されない
- 25. クラスの他のメソッドが呼び出されたときに、クラスのメソッドを呼び出す方法(Ruby)
- 26. RecyclerViewアダプタ呼び出されないメソッド
- 27. 単体テスト中にメソッド呼び出しが試行されたが、実際には呼び出していないが、実際には呼び出さない
- 28. メソッドの呼び出しが
- 29. なぜTreeViewer.refresh()を呼び出すとcontentProviderのgetChildren(Object)メソッドが呼び出されないのですか?
- 30. ListPreferencesが変更されたときにonPreferenceChangeメソッドが呼び出されない
ReSharperのは、メンバ変数を外部時々ロックの内側に時々使用される状況を検索します。 –
@Bernhard Hiller、この分野のResharperの能力は非常に限られています。限られたケースのサブセットしか捕捉しない静的解析に基づいています。 – user626528
通常の「ロック(オブジェクト)」文を使用して、何も変更せずにそれを実行できるようにしたいですか?私はあなたがデバッグモードで必要な情報を提供するいくつかのオブジェクトラッパーを使用してそれを行うことができると想像することができます。 – Evk