《clr via c#》3rd中提到,應該以執行緒安全的方式引發事件,不禁冒冷汗,一直以來還真沒注意到這個問題,以前寫的不少**得重新審查修正了。下面是引用原文說明:
.net framework最初發布時,是建議開發者用以下方式引發事件:
protected這個onnewmail方法的問題在於,執行緒可能發現newmail不為null,然後,就在呼叫newmail之前,另乙個執行緒從委託鏈中移除了乙個委託,是newmail變成了null。這會造成丟擲乙個nullreferenceexception異常。virtual
void
onnewmail(newmaileventargs e)
於是我寫了以下**測試重現這種執行緒競態的情況:
**
using我測試了好幾次,index最小的一次是60多,最大的1000多,併發問題還是比較明顯的。下面是其中一次測試結果:system;
using
system.threading;
using
system.diagnostics;
namespace
neutra.utils
static
void
addandremoveeventhandler(
object
obj)
}static
void
handleevent(
object
sender, eventargs e)
static
void
test1()
thread.sleep(0);
}console.writeline();
}catch
(exception exception)
, time:
", i, sw.elapsed);
console.writeline(exception);
}finally
}static
void
test2()
thread.sleep(0);
}console.writeline();
}catch
(exception exception)
, time:
", i, sw.elapsed);
console.writeline(exception);
}finally}}
}
有些人傾向於使用eventhandler handler = instance.myevent;代替使用interlocked.compareexchange方法,書中也提到了,這種方式也是可行的,因為ms的jit編譯器不會將這裡的handler優化掉。書中最後說道「另外由於事件主要在單執行緒的情形中使用(winform/wpf/silverlight),所以執行緒安全並不是乙個問題。」
我認為,這個問題還是有必要注意一下的。這種問題一般都很難重現,而且還是該死的nullreferenceexception異常,一看上下文**,霎時間還真是「莫名其妙」,最後歸於人品問題倒是相當無奈了。
今天發現**中有誤,interlocked.exchange會交換兩引用,應該使用interlocked.compareexchange方法。(上面**已修正)
以ThreadStart方式實現多執行緒
使用threadstart委託 這裡先以乙個例子體現一下多執行緒帶來的好處,首先在message類中建立乙個方法showmessage 裡面顯示了當前執行執行緒的id,並使用thread.sleep int 方法模擬部分工作。在main 中通過threadstart委託繫結message物件的sho...
由Action是否是執行緒安全的引發的思考
不知道從哪個地方入的口,一直看到action是否是安全的,在網上找了一大通答案。亂的很,有的說action是執行緒安全的,有的說是執行緒不安全的。最後發現,原來說執行緒安全的是基於struts2的,而說執行緒不安全的是基於struts1的。總結 struts1中,每乙個action在web容器中只會...
執行緒安全處理的3種方式
本次電影的座位共 100個 本場電影只能賣100張票 如下 public class tickects implements runnable catch interruptedexception e system.out.println thread.currentthread getname 售...