Here's a knowledge base article that lists all the ways that can cause code you desire to be executed asynchronously to actually run synchronously.
Asynchronous Disk I/O Appears as Synchronous on Windows NT, Windows 2000, and Windows XP
Does anything on the list apply to your situation?
Have you tried implementing the same behavior with .NET 4.5's ReadAsync method?
I am quoting from MSDN:
In the .NET Framework 4 and earlier versions, you have to use methods such as BeginRead and EndRead to implement asynchronous I/O operations. These methods are still available in the .NET Framework 4.5 to support legacy code; however, the new async methods, such as ReadAsync, WriteAsync, CopyToAsync, and FlushAsync, help you implement asynchronous I/O operations more easily.
EDIT I am reproducing your issue with a 256MB file on OCZ Vertex 2 with ICH10 and Windows 7. I am having to generate the file, reboot the PC to clear file cache, and then try and read the same file.
using System;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;
using System.Threading;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
string fileName = @"C:\Temp\a1.txt";
int arraySize = 512 * 1024 * 1024;
var bytes = new byte[arraySize];
new Random().NextBytes(bytes);
// This prints false, as expected for async call
var callback = new AsyncCallback(result =>
Console.WriteLine("Completed Synchronously: " + result.CompletedSynchronously));
try
{
// Use this method to generate file...
//WriteFileWithRandomBytes(fileName, arraySize, bytes, callback);
Console.WriteLine("ReadFileAsync invoked at " + DateTimeOffset.Now);
var task = ReadFileAsync(fileName);
Console.WriteLine("ReadFileAsync completed at " + DateTimeOffset.Now);
Task.WaitAll(task);
Console.WriteLine("Wait on a read task completed at " + DateTimeOffset.Now);
}
finally
{
if (File.Exists(fileName))
File.Delete(fileName);
}
}
private static void WriteFileWithRandomBytes(string fileName, int arraySize, byte[] bytes, AsyncCallback callback)
{
using (var fileStream = new FileStream(fileName,
FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, 128 * 1024, FileOptions.Asynchronous))
{
Console.WriteLine("BeginWrite invoked at " + DateTimeOffset.Now);
var asyncResult = fileStream.BeginWrite(bytes, 0, arraySize, callback, null);
Console.WriteLine("BeginWrite completed at " + DateTimeOffset.Now);
// completes in 6 seconds or so... Expecting instantaneous return instead of blocking
// I expect runtime to block here...
Task.WaitAll(Task.Factory.FromAsync(asyncResult, fileStream.EndWrite));
// or at least when flushing the stream on the following end-curly
}
}
private static Task<int> ReadFileAsync(string filePath)
{
FileInfo fi = new FileInfo(filePath);
byte[] buffer = new byte[fi.Length];
var file = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None, 64 * 1024, FileOptions.Asynchronous);
Task<int> task = Task<int>.Factory.FromAsync(file.BeginRead, file.EndRead, buffer, 0, buffer.Length, null);
return task.ContinueWith(t =>
{
file.Close();
Console.WriteLine("Done ReadFileAsync, read " + t.Result + " bytes.");
return t.Result;
});
}
}
}
When all else fails, here's the reference to unmanaged API documentation.