2011-10-12 18 views
1

是否有記錄,一個線程在日誌當線程在抵達lock語句

lock(x) 
{ 
    //do work on a collection 

} 

等待鎖當一個線程到達一個快捷方式等什麼?

如果線程1到達鎖,並且塊中沒有另一個線程,則不應該有日誌。然後,如果線程2到達鎖(x)並且線程1仍在該塊中,則應該有日誌。理想的解決方案不需要切換到Mutex或Monitor就會增加很多複雜性。如果使用TPL,PLINQ或RX的話,有一種快速簡單的方法可以做到這一點。

+2

我想你將不得不擴大''鎖'短手到它的長期等效和手動插入日誌記錄。 – bzlm

+0

當我說理想的解決方案不需要切換到Mutex時,我的意思是它不需要明確使用Mutex或Monitor。我編輯了最初的問題來反映這一點。我確實需要這樣做只是爲了調試,並希望保持語法儘可能簡單。 – Tion

+1

然後PostSharp是要走的路。 – bzlm

回答

8

您可以de-sugar the lock statement並使用Monitor.TryEnter檢查,如果鎖無需等待被收購:

bool lockTaken = false; 
var obj = x; 
try 
{ 
    Monitor.TryEnter(obj, ref lockTaken); 
    if (!lockTaken) 
    { 
     Log(); 
     Monitor.Enter(obj, ref lockTaken); 
    } 
    //do work on a collection 
} 
finally 
{ 
    if (lockTaken) 
    { 
     Monitor.Exit(obj); 
    } 
} 
2

使用標準lock()聲明無法輕鬆完成此操作。您可以使用Monitor.TryEnter()嘗試輸入鎖,然後在方法返回false時記錄一些內容。

2

你爲什麼要試圖做到這一點?如果是用於調試或分析目的,則可以使用非託管CLR分析或調試API。另一個想法是使用PostSharp或Afterthought等工具編譯後靜態修改IL代碼。 (請注意,Afterthought無法以目前的形式進行此操作,但由於您有源代碼,因此您可以破解此代碼。)

我建議您改爲修改代碼。我推薦這個,而不是dtb的語法:

if (!Monitor.TryEnter(x)) 
{ 
    Log(); 
    Monitor.Enter(x); 
} 
try 
{ 
    //do work on a collection 
} 
finally 
{ 
    Monitor.Exit(x); 
}