第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么不能在lock語句的主體內使用'await'運算符?

為什么不能在lock語句的主體內使用'await'運算符?

慕后森 2019-10-15 09:24:16
鎖定語句中不允許使用C#(.NET Async CTP)中的await關鍵字。從MSDN:等待表達式不能用于同步函數(shù),查詢表達式,異常處理語句的catch或finally塊,鎖語句的塊或不安全的上下文中。我認為由于某種原因,對于編譯器團隊而言,這既困難又不可能。我嘗試了using語句:class Async{    public static async Task<IDisposable> Lock(object obj)    {        while (!Monitor.TryEnter(obj))            await TaskEx.Yield();        return new ExitDisposable(obj);    }    private class ExitDisposable : IDisposable    {        private readonly object obj;        public ExitDisposable(object obj) { this.obj = obj; }        public void Dispose() { Monitor.Exit(this.obj); }    }}// example usageusing (await Async.Lock(padlock)){    await SomethingAsync();}但是,這無法正常工作。在ExitDisposable.Dispose中對Monitor.Exit的調用似乎無限期地(大部分時間)阻塞,導致死鎖,因為其他線程試圖獲取該鎖。我懷疑我的工作不可靠,而鎖語句中不允許使用await語句的原因與某種原因有關。有誰知道為什么鎖語句體內不允許等待?
查看完整描述

3 回答

?
千巷貓影

TA貢獻1829條經驗 獲得超7個贊

我認為由于某種原因,對于編譯器團隊而言,這既困難又不可能。


不,實施起來并非沒有困難或不可能,您自己實施的事實就證明了這一事實。相反,這是一個非常糟糕的主意,因此我們不允許這樣做,以防止您犯此錯誤。


在DisposeDisposable.Dispose中對Monitor.Exit的調用似乎無限期地(大部分時間)阻塞,導致死鎖,因為其他線程試圖獲取該鎖。我懷疑我的工作不可靠,而鎖語句中不允許使用await語句的原因與某種原因有關。


正確,您已經發(fā)現(xiàn)我們將其設為非法的原因。在鎖內部等待等待是產生死鎖的秘訣。


我敢肯定,您會明白為什么:在await將控制權返回給調用方與方法恢復之間的這段時間內,任意代碼都會運行。那個任意代碼可能會取出產生鎖順序倒置的鎖,從而導致死鎖。


更糟糕的是,代碼可能會在另一個線程上恢復(在高級方案中;通常您會在執(zhí)行等待的線程上再次接聽,但不一定),在這種情況下,解鎖將解鎖與所用線程不同的線程上的鎖開鎖。這是一個好主意嗎?沒有。


我注意到,出于相同的原因,對a進行yield return內部操作也是“最差的做法” lock。這樣做是合法的,但我希望我們將其定為非法。我們不會為“等待”犯同樣的錯誤。


查看完整回答
反對 回復 2019-10-15
?
藍山帝景

TA貢獻1843條經驗 獲得超7個贊

使用SemaphoreSlim.WaitAsync方法。


 await mySemaphoreSlim.WaitAsync();

 try {

     await Stuff();

 } finally {

     mySemaphoreSlim.Release();

 }


查看完整回答
反對 回復 2019-10-15
?
慕絲7291255

TA貢獻1859條經驗 獲得超6個贊

基本上,這將是錯誤的事情。


有兩個方面,這可以實現(xiàn):


保持鎖,只在塊的末尾釋放它。

這是一個非常糟糕的主意,因為您不知道異步操作將花費多長時間。您只應在最短時間內握住鎖。這也可能是不可能的,因為線程擁有一個鎖,而不是一個方法-并且您甚至可能沒有在同一線程上執(zhí)行其余的異步方法(取決于任務調度程序)。


釋放等待中的鎖,并在等待返回時重新獲取它。

這違反了IMO最小原則,在IMO中,異步方法的行為應與等效的同步代碼盡可能接近-除非您Monitor.Wait在鎖塊中使用,否則您希望在該區(qū)塊的持續(xù)時間內擁有該鎖。


因此,這里基本上有兩個相互競爭的需求-您不應該在這里嘗試第一個,而如果您想采用第二種方法,則可以通過用await表達式分隔兩個分開的鎖塊來使代碼更清晰:


// Now it's clear where the locks will be acquired and released

lock (foo)

{

}

var result = await something;

lock (foo)

{

}

因此,通過禁止您等待鎖塊本身,該語言迫使您考慮自己真正想做的事情,并在編寫的代碼中使選擇更清晰。


查看完整回答
反對 回復 2019-10-15
  • 3 回答
  • 0 關注
  • 3313 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號