亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

C#event線程安全

2019-11-14 13:34:04
字體:
來源:轉載
供稿:網友

突然想到有關C#中使用event特性時關于線程安全的問題,以前雖然有遵從“復制引用+null判斷”的模式(盲目地),但沒有深入了解和思考。

為之查詢了資料和實驗,對此有了進一步的理解。

 

一般event使用模式

定義(field-like event):

public event EventHandler Done;

類內raise:

PRotected void OnDone(){    var done = Done;    if (done != null)    {        done(this, new EventArgs());    }}

不禁要問,為何要復制引用?多線程下表現如何?

 

關于C#3.0和C#4.0中編譯器對event實現的整理

為了解決上面哪些疑惑,我查了一些資料,其中有來自當時C#編譯器開發組成員的一篇博文 Field-like Events Considered Harmful。

這篇博文介紹了C#3.0中編譯器對于field-like event(也是最常見的使用方式)的實現。

 

對于如此的代碼,

class EventInCS3{    public event EventHandler Done;}

編譯器會將其轉換成:

class EventInCS3{    private EventHandler __Done; // 1    public event EventHandler Done    {        add        {            lock (this) // 2            {                __Done = __Done + value; // 3            }        }        remove        {            lock (this) { __Done = __Done - value; }        }    }}

有以下幾點值得注意(同注釋編號):

1.event下隱藏的真正delegate鏈。實際上我們使用的是子類MulticastDelegate(可以參考 開源的coreclr實現)。

3.正如+、-操作符對于string類型是起字符串組合作用,其對于delegate類型也同樣是起到兩條鏈的組合作用(參考 MSDN),實際上是調用了Delegate.CombineDelegate.Remove。同時也引入了經典的線程問題(修改丟失)。

2.為了解決多線程問題,使用了lock。

(就先不管這個lock(this)了。當然上面提到的 博文 里提到了,編譯器并不是通過lock,繼而通過Monitor的靜態方法來同步,而是通過IL即MethodImplAttribute(MethodImplOptions.Synchronized)實現。這些都是C#本身不推薦的方法。)

 

而在C#4.0中,同步的實現有了變化,同樣參見同一作者兩年后的 這一篇博文。

編譯器默認的add、remove實現,改為使用compare and swap來實現lock-free同步。值得注意的是,delegate是不可更改的類型,即+=、-=之后,會指向一個新的對象,而不再是原對象(類似string)。

通過IL查看程序集里生成的add_Done、remove_Done,可以發現端倪,大致會生成如下的代碼:

static void add_Done(EventHandler value){    EventHandler V_0 = __Done;    EventHandler V_1, V_2;    do    {        V_1 = V_0;        V_2 = (EventHandler)Delegate.Combine(V_1, value);        V_0 = Interlocked.CompareExchange<EventHandler>(ref __Done, V_2, V_1);    } while (V_0 != V_1);}

 

C#4.0中event相關的語義變化整理

在同一作者的 另一篇博文 中,介紹了C#4.0中event相關的語義變化,主要是+=、-=操作符的語義變化

 

在C#3.0中,對于一個event,如果在該類之外訪問這個event,則會被認為是訪問這個event本身,如我們熟知的只能通過+=、-=這兩個操作符來訪問(即是調用對應的add、remove訪問器);而在類的內部,所有對這個event的訪問,都會被認為是訪問作為event實現的delegate本身(即訪問Done,實際上訪問到的是__Done)。

這么處理的話,我們就能在OnDone方法里復制引用,判斷null,進行調用。因為此時Done這個標識符,代表的是一個EventHandler對象的引用。

C#3.0的問題也在于此,這種情況下,我們寫下

Done += SomeHandlerMethod;

時,+=實際是調用了:

EventHandler EventHandler.Operator +(EventHandler left, EventHandler right)

在Visual Studio 2015里寫一個普通的、非event的EventHandler的+=運算,鼠標放在+=上時,顯示的也是這個函數簽名。C#3.0時即使對event也是這么處理的。

導致我們失去了默認add訪問器提供的同步功能。

 

而這一現象在C#4.0中得到了改善。在類內部訪問event的標識符時,+=、-=操作符就會被認為是add、remove的調用了。

可知在C#4.0寫下同樣的代碼時,+=調用的簽名為:

void EventInCS4.Done.add 

 

自定義event訪問器

自定義event時(非field-like event),我們自己編寫的add、remove訪問器就沒有默認的同步了。如果要考慮線程安全,需要手動加上同步(比如lock(someLockObject))。

此時,在類內部訪問event標識符,只會被當成是訪問event本身。要引發事件(Done)的話,需訪問對應delegate(__Done(this, new EventArgs()))。

 

操作event的正確方式

一般情況下無需自己實現event,用field-like就好了。

因為不管是通過event標識符訪問delegate(field-like event),還是直接訪問delegate(自定義event),我們得到的都是delegate對象的引用,而且delegate對象是不可更改的。引用的復制是原子的。所以我們可以隨意地復制該delegate的引用,然后判斷null并invoke。

 

一些code snippet如:

  1. 通過擴展方法來引發事件:
    public static class EventExtension{    public static void Raise<T>(this EventHandler<T> handler, object sender, T args)    {        if (handler != null)        {            handler(sender, args);        }    }    public static void Raise(this EventHandler handler, object sender, EventArgs args); // 重載版}

    delegate的引用會以pass-by-value形式得到復制,所以直接

    Done.Raise(this, new EventArgs());
  2.  通過C#6.0提供的Null-conditional操作符:
    Done?.Invoke(this, new EventArgs());

    null-conditional操作符也會進行引用的復制,所以是線程安全的。(沒有Done?(...)這種寫法)

 

對于編譯器是否會將復制引用作為重復的局部變量優化掉,以至于在一些情況下需要使用諸如以下的方式的問題,我沒有深入了解。

Interlocked.CompareExchange(ref Done, null, null);

簡單查詢一下之后,得知對于微軟自家的CLR無需關心這個問題,蓋其遵循較嚴格的內存模型(memory model),不會引入新的讀取操作。但其他情況下有可能存在這樣的問題。相關文章和討論鏈接如下:

  1. http://stackoverflow.com/questions/11159176/thread-safe-event-calls
  2. http://code.logos.com/blog/2008/11/events_and_threads_part_4.html
  3. Understand the Impact of Low-Lock Techniques in Multithreaded Apps MSDN Magazine Oct 2005 (需要下載chm看)

上一篇:編程概念

下一篇:Xamarin入門淺析

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩欧美在线观看| 久久九九精品99国产精品| 成人免费看吃奶视频网站| 亚洲欧美在线磁力| 伊人久久久久久久久久| 日韩欧美高清在线视频| 黑人与娇小精品av专区| 午夜精品一区二区三区视频免费看| 国产盗摄xxxx视频xxx69| 日韩最新免费不卡| 欧美电影免费观看大全| 欧美在线一区二区视频| 日韩av成人在线| 日韩**中文字幕毛片| 97精品国产97久久久久久| 亚洲精品狠狠操| 国产精品www网站| 国模精品视频一区二区| 国产成人免费av电影| 午夜精品免费视频| 国产专区欧美专区| 91豆花精品一区| 91色琪琪电影亚洲精品久久| 欧美性高跟鞋xxxxhd| 高潮白浆女日韩av免费看| 欧美亚洲第一区| 日韩精品中文字幕在线播放| 亚洲精品av在线播放| 精品中文字幕久久久久久| 日韩在线观看高清| 国模吧一区二区| 色在人av网站天堂精品| 日本高清视频一区| 国产精品一区二区三区免费视频| 成人午夜在线影院| 欧美在线亚洲在线| 日韩在线观看精品| 中文字幕日本欧美| 亚洲精品在线看| 久久精品国产亚洲7777| 日韩精品久久久久久久玫瑰园| www.日韩系列| 国产福利精品视频| 91欧美激情另类亚洲| 日韩精品在线第一页| 亚洲一区中文字幕| 欧美孕妇与黑人孕交| 欧美成人sm免费视频| 国产成人精品免高潮费视频| 91精品国产亚洲| 97视频在线观看免费高清完整版在线观看| 国内精品久久久久久中文字幕| 欧美性视频网站| 久久精品福利视频| 久久乐国产精品| 色综合视频网站| 黑人精品xxx一区一二区| 九九热精品视频国产| 久久亚洲综合国产精品99麻豆精品福利| 亚洲精品www久久久| 久久久欧美精品| 日韩电视剧在线观看免费网站| 欧美乱人伦中文字幕在线| 色吧影院999| 欧美日韩一二三四五区| 久久91精品国产91久久跳| 欧美亚洲一区在线| 亚洲精品99久久久久| 精品国产精品三级精品av网址| 欧美激情视频网站| 51ⅴ精品国产91久久久久久| 久久中文精品视频| 日韩高清电影好看的电视剧电影| 青草成人免费视频| 久久这里有精品视频| 久久久久一本一区二区青青蜜月| 欧美日韩在线免费观看| 国内精品久久久久久久| 九九热在线精品视频| 国产精品v片在线观看不卡| 一区二区三区久久精品| 这里只有精品丝袜| 久久免费高清视频| 国产精品视频一区二区高潮| 日韩欧美在线第一页| 亚洲男人7777| 欧美大片在线看免费观看| 国产午夜精品久久久| 国产精品久久久久999| 国产日韩欧美在线| 亚洲性69xxxbbb| 欧美国产日韩中文字幕在线| 中文字幕日本精品| 欧美日韩精品在线观看| 日本精品中文字幕| 丰满岳妇乱一区二区三区| 中国人与牲禽动交精品| 国产精品高精视频免费| 成人在线免费观看视视频| 久久香蕉精品香蕉| 精品二区三区线观看| 亚洲专区在线视频| 午夜精品一区二区三区在线视| 久久免费视频在线观看| 欧美大片在线看免费观看| 国产亚洲欧美一区| 日韩精品日韩在线观看| 日韩电视剧在线观看免费网站| 日韩免费av一区二区| 国产精品亚洲美女av网站| 成人激情春色网| 亚洲成人激情视频| 成人黄色片网站| 成人国产精品色哟哟| 日韩女优在线播放| 亚洲人午夜色婷婷| 久操成人在线视频| 日韩中文字幕免费视频| 高跟丝袜一区二区三区| 亚洲精品国产综合区久久久久久久| 亚洲福利视频网| 色与欲影视天天看综合网| 欧美精品999| 97人人爽人人喊人人模波多| 亚洲无av在线中文字幕| 91老司机精品视频| 久久精品国产视频| 91精品久久久久久久久青青| 日韩高清免费在线| 久久五月天综合| 国产一区二区三区在线观看视频| 亚洲男人的天堂在线播放| 亚洲伊人久久综合| 最新69国产成人精品视频免费| 亚洲精品wwww| 2019中文字幕在线观看| 欧美视频专区一二在线观看| 日韩av影院在线观看| 日韩精品中文字幕在线观看| 夜夜狂射影院欧美极品| 国色天香2019中文字幕在线观看| 亚洲成年人影院在线| 国产精品日韩av| 69**夜色精品国产69乱| 亚洲欧美日韩一区在线| 中文字幕少妇一区二区三区| 亚洲人成网站999久久久综合| 亚洲精品在线看| 日韩一区二区av| 国产www精品| 日韩在线免费视频观看| 在线观看视频99| 国产高清视频一区三区| 在线播放国产一区二区三区| 日韩在线视频播放| 中文字幕一区电影| 久久99热精品| 国内偷自视频区视频综合| 欧美国产欧美亚洲国产日韩mv天天看完整| 美女久久久久久久| 成人精品网站在线观看| www.99久久热国产日韩欧美.com| 三级精品视频久久久久| 日韩在线视频中文字幕|