【发布时间】:2014-03-19 20:44:55
【问题描述】:
试试这个。使用单个按钮和按钮单击事件的以下代码设置新的 Windows 窗体应用程序:
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重载打开文件时,我发现上述行为没有任何变化。
标签: c# asynchronous task-parallel-library