試試這個。安裝新的Windows窗體應用程序有一個按鈕,點擊按鈕單擊事件下面的代碼:FileStream.ReadAsync有時會同步完成嗎?
private async void button1_Click(object sender, EventArgs e)
{
using (var file = File.OpenRead(@"C:\Temp\Sample.txt"))
{
byte[] buffer = new byte[4096];
int threadId = Thread.CurrentThread.ManagedThreadId;
int read = await file.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
Debug.Assert(threadId != Thread.CurrentThread.ManagedThreadId);
}
}
然後運行該應用程序,然後單擊按鈕迅速。如果您的經歷與我的一樣,您會發現有時按預期工作,但其他時間Debug.Assert
將失敗。
根據我的ConfigureAwait
as explained on Stephen Cleary’s blog理解,通過對false
應該continueOnCapturedContext
指示不同步回「主」上下文(在這種情況下,UI線程)和執行應該繼續線程池的任務。
爲什麼然後斷言會隨機失敗?我只能假設ReadAsync
有時不會在後臺線程上完成,即它將同步完成。
此行爲是符合KB 156932 - Asynchronous Disk I/O Appears as Synchronous on Windows:
大多數I/O驅動程序(磁盤,通信和其他人)有特殊情況 碼的地方,如果一個I/O請求就可以完成「立即」,將完成 操作並且ReadFile或WriteFile函數 將返回TRUE。在所有方面,這些類型的操作似乎是同步的 。對於磁盤設備,通常,當數據緩存在內存中時,「立即」完成I/O請求。
我的假設和測試應用程序是否正確? ReadAsync
方法有時可以同步完成嗎?有沒有辦法保證執行將始終在後臺線程上繼續?
此問題對我的應用程序造成嚴重破壞,該應用程序使用COM對象,這些對象要求我始終知道哪個線程正在執行。
的Windows 7 64位,.NET 4.5.1
是否有原因,您不是在異步模式下打開文件? –
當使用指定「異步模式」的「FileStream」重載打開文件時,我發現上述行爲未發生任何變化。 – Jacob