gpt4 book ai didi

c# - FileOptions.Asynchronous 导致 FileStream.BeginRead 阻塞

转载 作者:行者123 更新时间:2023-11-30 15:36:52 26 4
gpt4 key购买 nike

为什么使用 FileOptions.Asynchronous 创建 FileStream 会导致 FileStream.BeginRead 阻塞调用线程?

这是代码片段:

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;
});
}

当使用 JetBrains dotPeek 挖掘 MSFT FileStream 代码时,他们的代码中似乎存在错误:

      if (!this._isAsync)
return base.BeginRead(array, offset, numBytes, userCallback, stateObject);
else
return (IAsyncResult) this.BeginReadAsync(array, offset, numBytes, userCallback, stateObject);

BeginRead 方法实际上似乎是通过调度任务进行异步读取,但 BeginReadAsync 方法实际上最终是进行同步读取。所以他们的方法命名命名法是倒退的,调用哪个方法的逻辑是错误的。如果 this._isAsync == true,则应调用 BeginRead。

因此,似乎要让 FileStream.BeginRead 立即返回(异步安排读取),您实际上必须将构造函数中的 useAsync 参数设置为 false。

最佳答案

这是一篇知识库文章,其中列出了所有可能导致您希望异步执行的代码实际同步运行的方法。

Asynchronous Disk I/O Appears as Synchronous on Windows NT, Windows 2000, and Windows XP

列表中的任何内容是否适用于您的情况?

您是否尝试过使用 .NET 4.5 的 ReadAsync method 实现相同的行为? ?

我引用自 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.

编辑 我正在使用 ICH10 和 Windows 7 在 OCZ Vertex 2 上用一个 256MB 的文件重现您的问题。我必须生成该文件,重新启动 PC 以清除文件缓存,然后尝试读取同一个文件。

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;
});
}
}
}

当所有其他方法都失败时,here's the reference to unmanaged API documentation .

关于c# - FileOptions.Asynchronous 导致 FileStream.BeginRead 阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13299705/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com