C# 异步导致FileStream.beginhead阻塞
为什么使用FileOptions.Asynchronous创建FileStream会导致FileStream.BeginRead阻止调用线程 以下是代码片段:C# 异步导致FileStream.beginhead阻塞,c#,.net,asynchronous,filestream,beginread,C#,.net,Asynchronous,Filestream,Beginread,为什么使用FileOptions.Asynchronous创建FileStream会导致FileStream.BeginRead阻止调用线程 以下是代码片段: private static Task<int> ReadFileAsync(string filePath) { var file = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, 64 *
private static Task<int> ReadFileAsync(string filePath)
{
var file = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, 64 * 1024, FileOptions.Asynchronous);
FileInfo fi = new FileInfo(filePath);
byte[] buffer = new byte[fi.Length];
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;
});
}
BeginRead方法实际上似乎通过调度任务来异步读取,但BeginReadAsync方法实际上最终执行同步读取。
因此,他们的方法命名法是反向的,调用哪个方法的逻辑是错误的。如果出现以下情况,则应调用BeginRead.\u isAsync==true
因此,要让FileStream.BeginRead立即返回(异步安排读取),实际上必须将coConstructor中的UseAync参数设置为false。这里有一篇知识库文章,列出了所有可能导致希望异步执行的代码实际同步运行的方法 清单上有什么东西适合你的情况吗 您是否尝试过在.NET 4.5中实现相同的行为 我引用MSDN的话: 在.NET Framework 4和早期版本中,必须使用BeginRead和EndRead等方法来实现异步I/O操作。这些方法在.NET Framework 4.5中仍然可用,以支持遗留代码;但是,新的异步方法(如ReadAsync、WriteAsync、CopyToAsync和FlusAsync)可以帮助您更轻松地实现异步I/O操作 编辑我用ICH10和Windows 7在OCZ Vertex 2上的256MB文件复制您的问题。我必须生成文件,重新启动电脑以清除文件缓存,然后尝试读取相同的文件
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;
});
}
}
}
使用系统;
使用System.Threading.Tasks;
使用System.IO;
使用系统诊断;
使用系统线程;
命名空间控制台应用程序4
{
班级计划
{
静态void Main(字符串[]参数)
{
字符串文件名=@“C:\Temp\a1.txt”;
int arraySize=512*1024*1024;
var bytes=新字节[arraySize];
新的Random().NextBytes(字节);
//这将输出false,正如异步调用所预期的那样
var callback=新的异步回调(结果=>
WriteLine(“同步完成:+result.CompletedSynchronously”);
尝试
{
//使用此方法生成文件。。。
//WriteFileWithRandomBytes(文件名、数组大小、字节、回调);
WriteLine(“ReadFileAsync在“+DateTimeOffset.Now”处调用);
var task=ReadFileAsync(文件名);
WriteLine(“ReadFileAsync在”+DateTimeOffset.Now完成);
Task.WaitAll(任务);
WriteLine(“等待在“+DateTimeOffset.Now”完成的读取任务);
}
最后
{
if(File.Exists(fileName))
删除(文件名);
}
}
私有静态void WriteFileWithRandomBytes(字符串文件名,int-arraySize,字节[]字节,异步回调)
{
使用(var fileStream=newfilestream)(文件名,
FileMode.OpenOrCreate,FileAccess.Write,FileShare.None,128*1024,FileOptions.Asynchronous)
{
WriteLine(“在“+DateTimeOffset.Now”处调用BeginWrite);
var asyncResult=fileStream.BeginWrite(字节,0,数组化,回调,null);
WriteLine(“BeginWrite在“+DateTimeOffset.Now”完成);
//大约在6秒钟内完成…期望即时返回而不是阻塞
//我希望运行时在这里阻塞。。。
Task.WaitAll(Task.Factory.fromsync(asyncResult,fileStream.EndWrite));
//或者至少在冲洗下一端的水流时卷曲
}
}
私有静态任务ReadFileAsync(字符串文件路径)
{
FileInfo fi=新的FileInfo(filePath);
字节[]缓冲区=新字节[fi.Length];
var file=new FileStream(filePath,FileMode.Open,FileAccess.Read,FileShare.None,64*1024,FileOptions.Asynchronous);
Task Task=Task.Factory.fromsync(file.BeginRead、file.EndRead、buffer、0、buffer.Length、null);
返回任务。继续(t=>
{
file.Close();
WriteLine(“Done ReadFileAsync,read”+t.Result+“bytes”);
返回t.Result;
});
}
}
}
当所有其他操作都失败时,.是否尝试传入有效的stateObject,而不是null?与处的代码相比,您打算用发布的代码片段显示什么?我无法从中获得任何信息。上面发布的代码将重现执行线程阻塞在线Task.Factory.FromAsync(…)的行为,直到文件读取完成。所以本质上它做的与我期望的相反,它以同步方式而不是异步方式读取文件。这种行为让我感到困惑……我不确定这是否适用。很难说。您是否能够使用我发布的代码片段在您的计算机上重新设置此行为?我已尝试使用async/await和FileStream.ReadAsync方法实现此行为,但没有看到此行为。我看到了预期的异步读取行为。
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;
});
}
}
}