Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步导致FileStream.beginhead阻塞_C#_.net_Asynchronous_Filestream_Beginread - Fatal编程技术网

C# 异步导致FileStream.beginhead阻塞

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 *

为什么使用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;
     });
  }
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;
         });
      }
   }
}