C# APM和断点上未解析的System.AccessViolationException异常

C# APM和断点上未解析的System.AccessViolationException异常,c#,asynchronous,filestream,iasyncresult,C#,Asynchronous,Filestream,Iasyncresult,考虑以下功能: static void Main(string[] args) { FileStream fs = new FileStream("e:\\temp.txt", FileMode.Open); int size = (int)fs.Length; byte[] data = new byte[size]; IAsyncResult result = fs.BeginRead(data, 0, size, new AsyncCallback(Cal

考虑以下功能:

static void Main(string[] args)
{
    FileStream fs = new FileStream("e:\\temp.txt", FileMode.Open);
    int size = (int)fs.Length;

    byte[] data = new byte[size];
    IAsyncResult result = fs.BeginRead(data, 0, size, new AsyncCallback(Callback), fs);

    Console.ReadLine();
}
问题1: 如果在起始行上放置断点,并在调试模式下运行程序,则会出现以下错误:

MyApp.exe中发生类型为“System.AccessViolationException”的未处理异常

但是,如果我将断点放在ReadLine行上并执行相同的操作,则不会发生错误。我相信将FileStream实例作为最后一个参数传递给beginhead函数会导致问题,但是,我不知道那里发生了什么

---UPDATE1:您可能会问我为什么试图将“fs”传递给回调。是的,我可以将其作为成员变量保存,但是如果我要异步读取多个文件呢?这样,保存文件流的数组(或列表)将是不合理的

问题2: 此外,IAsyncResult的定义如下:

[ComVisible(true)]
public interface IAsyncResult
{
    object AsyncState { get; }
    WaitHandle AsyncWaitHandle { get; }
    bool CompletedSynchronously { get; }
    bool IsCompleted { get; }
}
MyClass c = new MyClass();
IMyInterface my = c.GetMyInterface();
但是,在跟踪代码时,我注意到IAsyncResult上的其他成员:

这怎么可能?IAsyncResult显然是由ReadWriteTask类实现的(在本例中),但是,我不知道这些其他属性来自何处

——更新2: 我尝试使用以下代码模拟相同的情况:

public interface IMyInterface
{
    int Prop1 { get; }
}

public class Impl : IMyInterface
{
    public int Prop1 { get { return 101; } }
    public int Prop2 { get { return 202; } }
}

public class MyClass
{
    public IMyInterface GetMyInterface()
    {
        Impl impl = new Impl();
        return impl;
    }
}
要调用该方法,我只需实例化一个MyClass并调用GetMyInterface方法,如下所示:

[ComVisible(true)]
public interface IAsyncResult
{
    object AsyncState { get; }
    WaitHandle AsyncWaitHandle { get; }
    bool CompletedSynchronously { get; }
    bool IsCompleted { get; }
}
MyClass c = new MyClass();
IMyInterface my = c.GetMyInterface();
但是,当我在Quickwatch中查看my变量时,我看到了非平坦的结果,这对我来说完全没有问题。但是,IAsyncResult/ReadWriteTask的情况不同。有什么区别


IAsyncResult
只是一个接口。您可以很容易地看到,本例中变量的实际类型是
System.IO.Stream.ReadWriteTask
——它只实现了接口
IAsyncResult
。这意味着它必须具有
IAsyncResult
的属性,但它也可以拥有它想要的任何其他属性。如果将变量强制转换为
ReadWriteTask
,您也将看到IntelliSense中的其他属性和方法,并且您可以使用它们(尽管您可能不应该这样做)。您可能想重新学习一下
接口
是什么

确保该文件实际上是可访问的。您可能正在执行阻止您在代码中成功打开文件的操作-例如,在其他应用程序中打开文件

没有理由将文件流作为状态传递。不过也不应该痛

另外,为什么要使用
BeginRead
?您正在运行.NET 4.5(正如
BeginRead
返回的
ReadWriteTask
所证明的那样),那么为什么不简单地使用
var bytesRead=wait fs.ReadAsync(…)?事实上,如果使用得当,您根本不需要
读线
——您应该等待实际正在做的事情完成

当然,在这种情况下,异步I/O毫无意义,但我假设这只是一个示例,您打算用它做一些更有用的事情

编辑

这是一个完整的工作代码段,不会显示您的错误:

using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AsyncFileStream
{
  class Program
  {
    static void Main(string[] args)
    {
      FileStream fs = new FileStream("d:\\temp.txt", FileMode.Open);
      int size = (int)fs.Length;

      byte[] data = new byte[size];

      var result = 
          fs.BeginRead(data, 0, size, (ar) => Callback(fs, ar, data), null);

      if (result.CompletedSynchronously) Callback(fs, result, data);

      Console.ReadLine();
    }

    static void Callback(FileStream fs, IAsyncResult ar, byte[] data)
    {
      var bytesRead = fs.EndRead(ar);

      Console.WriteLine(UTF8Encoding.UTF8.GetString(data, 0, bytesRead));
    }
  }
}
这是否显示与代码相同的错误?如果没有,您可能需要为回调方法添加代码,可能还需要一些更相关的信息


免责声明:这仍然是读取文件的糟糕方式。无法保证一次读取就能获得所有数据,事实上,通常一次读取整个文件是一种巨大的资源浪费,完全没有必要。

我100%肯定,该文件是可以访问的。如问题中所述,只需移动断点即可发生错误。对于另一个问题,如果密切关注“快速观察”窗口,您将看到所有属性都被展平,这在使用我自己的界面时是不可能的。另一方面,ReadWriteTask是在抽象流类中定义的“私有”、“密封”类。因此,情况并非如此。还有别的想法吗?(是的,这只是一个示例,我不打算使用它)。@JoeBank您仍然混淆了类和接口。属性被“展平”,因为没有基本类型
IAsyncResult
——您只看到类型
Task
的属性,它恰好实现了
IAsyncResult
。由于继承链中没有其他类具有自己的公共属性或方法,因此您将看到
任务
。当您使用自己的接口时,也会发生同样的情况。另外,
ReadWriteTask
private sealed
这一事实与此完全无关。返回值是
IAsyncResult
,这很重要。它是
Task
这一事实是一个实现细节。好吧,我在一个干净的控制台应用程序中尝试了你的代码,但仍然发生了相同的错误(如果我将断点放在起始行)。也许调试器试图做一些破坏内存的事情,我不知道。同样的事情也会发生在你身上吗?我正在使用Win7(64位),.NET Framework 4.5,Visual Studio 2013更新2。我更新了类/接口问题(更新2)。请你检查一下好吗?我真的需要了解那里发生了什么。谢谢你。@JoeBank事实上,我的配置与你的配置完全相同,我没有你遇到的问题。可能需要重新安装Visual Studio吗?:D我见过调试器有几次出现问题(但我的计算机上从未出现过),因此我想如果调试器的环境出现问题,它可能会变得有点挑剔。您是否在VS?中安装了任何附加组件。NET Reflector和ReSharper经常会破坏VS:)Ad更新1:如果这样做,那么输出缓冲区(
数据
)存储在哪里?您的封装完全错误,处理请求所需的所有结构都应该与主代码分开。似乎有一些细微的差别我们是无知的