假設我有這樣的示例代碼
var t = Float();
...
t.Wait()。
async Task Float()
{
while (LoopIsAllowed)
{
TryToComplete()。
System.Threading.Thread.Sleep(500)。
}
}
在這種情況下,代碼是同步運行的,而我有警告 "async方法缺乏'await'"。我真的需要以異步方式運行Float(),所以這個警告幾乎都應該被考慮。在我看來,這里的問題是,如果我呼叫Float()并等待它,那么應用程式將無法按預期作業,它將停留在var t = Float()而不是t.Wait()
但我沒有看到任何方法來解決這個問題,除了像這樣:
async Task Float()
{
while (LoopIsAllowed)
{
TryToComplete()。
await Task.Run(() => System.Threading.Thread.Sleep(500) )。
}
這種修復方式有意義嗎?就記憶體和處理器資源而言,呼叫Task.Run就可以了,還是有更好的方法?
在我看來,修復后呼叫var t = Float()將強制代碼同步運行,直到await Task.Run到達。然后父代碼將繼續執行,直到t.Wait()。只有到那時,它才會繼續通過while (LoopIsAllowed)回圈進行迭代。而這種行為正是我所需要的。
這樣做對嗎?
這是否正確?
編輯。 如果我的代碼中根本沒有任何延遲,我應該怎么做?而且沒有其他地方可以等待。我應該直接添加延遲嗎?或者我應該分析代碼并在消耗時間的計算塊周圍的某個地方添加Task.Run?
uj5u.com熱心網友回復:
千萬不要在異步方法中使用Thread.Sleep。
使用await Task.Delay();而不是Thread.Sleep
async Task Float()
{
while (LoopIsAllowed)
{
TryToComplete()。
await Task.Delay(500) 。
}
}
并且在主方法中使用GetAwaiter().GetResult()而不是wait
var t = Float().GetAwaiter() .GetResult();
uj5u.com熱心網友回復:
如果你的意圖是引入并行性,通過使用Task.Run方法將同步作業卸載到ThreadPool的最佳位置是可能的上層。這意味著一般來說應該避免將Task.Runs隱藏在方法鏈的深處。這篇文章中解釋了其中的道理。我應該為同步方法暴露異步包裝器嗎?在你的例子中,(名字不恰當)Float方法做同步作業,所以它應該是一個具有void回報型別的同步方法。然后你可以像這樣把它卸載到ThreadPool中:
Task t = Task.Run(() => Float() )。
//...
t.Wait()。
Task.Run是一個聰明的小方法,它同樣可以處理同步和異步的委托(具有Task回傳型別的委托)。因此,如果你以后決定通過將Float方法轉換為混合的同步-異步方法來提高其效率(關于執行緒的利用),你可以在不改變呼叫站點的任何東西的情況下完成(除了現在應該有Async后綴的方法的名稱):
async Task FloatAsync()
{
while (LoopIsAllowed) //potential code smell here. LoopIsAllowed是不穩定的嗎?
{
TryToComplete()。
await Task.Delay(500) 。
}
}
Task t = Task.Run(() => FloatAsync() )。
//...
t.Wait()。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/306659.html
標籤:
上一篇:引數停留在輸入Razor上C#
