我在尋找一個(gè)解釋,而不僅僅是一個(gè)解決方案。我已經(jīng)知道了解決方案。盡管花了幾天時(shí)間研究有關(guān)基于任務(wù)的異步模式(TAP),異步和等待的MSDN文章,但我對(duì)某些更詳細(xì)的信息仍然感到困惑。我正在為Windows Store Apps編寫記錄器,并且希望同時(shí)支持異步和同步記錄。異步方法遵循TAP,同步方法應(yīng)該隱藏所有這些內(nèi)容,并且外觀和工作方式與普通方法類似。這是異步日志記錄的核心方法:private async Task WriteToLogAsync(string text){ StorageFolder folder = ApplicationData.Current.LocalFolder; StorageFile file = await folder.CreateFileAsync("log.log", CreationCollisionOption.OpenIfExists); await FileIO.AppendTextAsync(file, text, Windows.Storage.Streams.UnicodeEncoding.Utf8);}現(xiàn)在對(duì)應(yīng)的同步方法...版本1:private void WriteToLog(string text){ Task task = WriteToLogAsync(text); task.Wait();}看起來(lái)正確,但是不起作用。整個(gè)程序永久凍結(jié)。版本2:嗯..也許任務(wù)沒有開始?private void WriteToLog(string text){ Task task = WriteToLogAsync(text); task.Start(); task.Wait();}這拋出 InvalidOperationException: Start may not be called on a promise-style task.版本3:嗯.. Task.RunSynchronously聽起來(lái)很有希望。private void WriteToLog(string text){ Task task = WriteToLogAsync(text); task.RunSynchronously();}這拋出 InvalidOperationException: RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.版本4(解決方案):private void WriteToLog(string text){ var task = Task.Run(async () => { await WriteToLogAsync(text); }); task.Wait();}這可行。因此,2和3是錯(cuò)誤的工具。但是1?1有什么問(wèn)題,與4有什么區(qū)別?是什么導(dǎo)致1凍結(jié)?任務(wù)對(duì)象有問(wèn)題嗎?有沒有明顯的僵局?
3 回答

鳳凰求蠱
TA貢獻(xiàn)1825條經(jīng)驗(yàn) 獲得超4個(gè)贊
async從同步代碼中調(diào)用代碼可能非常棘手。
我在博客上解釋了造成這種僵局的全部原因。簡(jiǎn)而言之,每個(gè)上下文的開頭都有一個(gè)默認(rèn)保存的“上下文”,await用于恢復(fù)該方法。
因此,如果在UI上下文中調(diào)用await此async方法,則在完成時(shí),該方法將嘗試重新輸入該上下文以繼續(xù)執(zhí)行。不幸的是,使用Wait(或Result)的代碼將在該上下文中阻塞線程,因此該async方法無(wú)法完成。
避免這種情況的準(zhǔn)則是:
使用ConfigureAwait(continueOnCapturedContext: false)盡可能多地。這使您的async方法可以繼續(xù)執(zhí)行而不必重新輸入上下文。
一直使用async。使用await代替Result或Wait。
如果您的方法自然是異步的,那么(可能)您不應(yīng)該公開同步包裝器。
- 3 回答
- 0 關(guān)注
- 882 瀏覽
添加回答
舉報(bào)
0/150
提交
取消