3 回答

TA貢獻(xiàn)1829條經(jīng)驗(yàn) 獲得超7個(gè)贊
我認(rèn)為由于某種原因,對于編譯器團(tuán)隊(duì)而言,這既困難又不可能。
不,實(shí)施起來并非沒有困難或不可能,您自己實(shí)施的事實(shí)就證明了這一事實(shí)。相反,這是一個(gè)非常糟糕的主意,因此我們不允許這樣做,以防止您犯此錯(cuò)誤。
在DisposeDisposable.Dispose中對Monitor.Exit的調(diào)用似乎無限期地(大部分時(shí)間)阻塞,導(dǎo)致死鎖,因?yàn)槠渌€程試圖獲取該鎖。我懷疑我的工作不可靠,而鎖語句中不允許使用await語句的原因與某種原因有關(guān)。
正確,您已經(jīng)發(fā)現(xiàn)我們將其設(shè)為非法的原因。在鎖內(nèi)部等待等待是產(chǎn)生死鎖的秘訣。
我敢肯定,您會(huì)明白為什么:在await將控制權(quán)返回給調(diào)用方與方法恢復(fù)之間的這段時(shí)間內(nèi),任意代碼都會(huì)運(yùn)行。那個(gè)任意代碼可能會(huì)取出產(chǎn)生鎖順序倒置的鎖,從而導(dǎo)致死鎖。
更糟糕的是,代碼可能會(huì)在另一個(gè)線程上恢復(fù)(在高級方案中;通常您會(huì)在執(zhí)行等待的線程上再次接聽,但不一定),在這種情況下,解鎖將解鎖與所用線程不同的線程上的鎖開鎖。這是一個(gè)好主意嗎?沒有。
我注意到,出于相同的原因,對a進(jìn)行yield return內(nèi)部操作也是“最差的做法” lock。這樣做是合法的,但我希望我們將其定為非法。我們不會(huì)為“等待”犯同樣的錯(cuò)誤。

TA貢獻(xiàn)1843條經(jīng)驗(yàn) 獲得超7個(gè)贊
使用SemaphoreSlim.WaitAsync方法。
await mySemaphoreSlim.WaitAsync();
try {
await Stuff();
} finally {
mySemaphoreSlim.Release();
}

TA貢獻(xiàn)1859條經(jīng)驗(yàn) 獲得超6個(gè)贊
基本上,這將是錯(cuò)誤的事情。
有兩個(gè)方面,這可以實(shí)現(xiàn):
保持鎖,只在塊的末尾釋放它。
這是一個(gè)非常糟糕的主意,因?yàn)槟恢喇惒讲僮鲗⒒ㄙM(fèi)多長時(shí)間。您只應(yīng)在最短時(shí)間內(nèi)握住鎖。這也可能是不可能的,因?yàn)榫€程擁有一個(gè)鎖,而不是一個(gè)方法-并且您甚至可能沒有在同一線程上執(zhí)行其余的異步方法(取決于任務(wù)調(diào)度程序)。
釋放等待中的鎖,并在等待返回時(shí)重新獲取它。
這違反了IMO最小原則,在IMO中,異步方法的行為應(yīng)與等效的同步代碼盡可能接近-除非您Monitor.Wait在鎖塊中使用,否則您希望在該區(qū)塊的持續(xù)時(shí)間內(nèi)擁有該鎖。
因此,這里基本上有兩個(gè)相互競爭的需求-您不應(yīng)該在這里嘗試第一個(gè),而如果您想采用第二種方法,則可以通過用await表達(dá)式分隔兩個(gè)分開的鎖塊來使代碼更清晰:
// Now it's clear where the locks will be acquired and released
lock (foo)
{
}
var result = await something;
lock (foo)
{
}
因此,通過禁止您等待鎖塊本身,該語言迫使您考慮自己真正想做的事情,并在編寫的代碼中使選擇更清晰。
- 3 回答
- 0 關(guān)注
- 3341 瀏覽
添加回答
舉報(bào)