2013-01-08 44 views
6

我正在努力擺脫靜態代碼分析的一些警告。 在一個特定情況下,ManualResetEvent沒有處理。此resharper修復處置關閉警告是否有意義?

有問題的代碼在主線程上執行Func,並將調用線程阻塞一定的毫秒數。我意識到這聽起來像是一件奇怪的事情,但這不在這個問題的範圍之內,所以請耐心等待。

假設我添加一個using聲明,如下所示:

object result = null; 
using (var completedEvent = new ManualResetEvent(false)) 
{ 
    _dispatcher.BeginInvoke((Action)(() => 
     { 
      result = someFunc; 
      completedEvent.Set(); // Here be dragons! 
     })); 

    completedEvent.WaitOne(timeoutMilliseconds); 
    return result; 
} 

現在,我意識到,這很可能會導致問題。我也碰巧使用Resharper,它警告我「消息處理已關閉」。

ReSharper的建議,通過改變問題的行來解決這個問題:

if (completedEvent != null) 
{ 
    completedEvent.Set(); 
} 

現在,提出的解決方案令我費解。在正常情況下,沒有理由將變量設置爲null by using聲明。 是否有一些在.NET中關閉的實現細節,可以保證變量在被關閉的變量處理後變爲null

作爲一個獎金問題,如何處置ManualResetEvent的問題會是一個很好的解決方案?

+1

@Steven爲什麼委託必須使用'completedEvent'的副本?你能解釋這一點嗎? –

回答

6

您正在混合ReSharper的「快速修復」和「上下文操作」。當ReSharper提出解決某些問題時,最有可能在那裏看到一個燈泡。您在此處看不到燈泡,因爲此警告沒有快速修復。

但是除了快速修復之外,ReSharper還具有「上下文操作」,它可以在其中爲您執行一些常規任務(將它們想象爲一個小的重構)。當ReSharper對光標下的代碼有上下文動作時,它會顯示一個選擇。在這裏您會看到一個名爲「檢查某些內容是否爲空」的上下文操作。它與警告沒有關係,並且沒有約定在處理變量後將被設置爲空。

另外,當您按下Alt-Enter鍵時,您會看到一個向外突出的燈泡,讓您覺得ReSharper不會爲此警告提供任何快速修復,但可以通過註釋禁用它。事實上,這是使此警告輕鬆消失的唯一方法。但我會改寫這段代碼。

2

我幾小時前就遇到了這個問題。

這是虛驚一場。 R#不明白執行會阻塞,直到事件被設置,儘管這會推遲處理完全正確的時刻。

IMO這是一個很好的解決方案。只要忽略R#。

如果超時已過並且事件已被處置,當您致電completedEvent.Set()時建議捕獲ObjectDisposedException。我不認爲這會阻止R#警告,但它是安全的。

+1

「執行會阻塞,直到事件設置」執行不會阻塞,它會在超時後運行。 –

+0

Oof。是。錯過了超時時間。我非常喜歡與自己的代碼相似,所以我錯過了這一點。 – spender

+0

正如@Hamlet所提到的那樣,在處理超時的情況下,可能會調用Set()方法。我在一段非常類似的代碼中捕獲了ObjectDisposedException。這是我當時可以想到的最安全的解決方案,但我更喜歡沒有例外的解決方案。 – Thorarin

1

我想,你必須檢查null,而且你必須捕獲這個異常。 想象一下,如果someFunc的運行次數超過timeoutMilliseconds,會發生什麼情況。