【问题标题】:BinaryReader throws NullReferenceException when being disposedBinaryReader 在处理时抛出 NullReferenceException
【发布时间】:2013-09-15 15:05:26
【问题描述】:

我有一个类MyClass,它需要文件中的数据,该文件将在整个程序运行期间使用。要读入数据,我有另一个类OpenFileService,它派生自IDisposable,并使用BinaryReader 读入所有数据:

internal class OpenFileService : IDisposable
{
    #region disposing data
    bool disposed = false;

    public void Dispose()
    {
        if (!disposed)
        {
            Dispose(true);
            GC.SuppressFinalize(this);
            disposed = true;
        }
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            br.Dispose();
        }
    }

    ~OpenFileService()
    {
        Dispose(false);
    }
    #endregion

    internal event EventHandler ErrorInFileReadEventHandler;
    internal event EventHandler SuccessfulFileReadEventHandler;

    private BinaryReader br;

    internal void OpenFile(object obj)
    {
        MyClass sender = obj as MyClass;
        bool isWrongFormat = false;

        try
        {
            br = new BinaryReader(File.Open((sender).fileName, FileMode.Open));
            //read in header from file.
            if (//header shows wrong file format)
            {     
                isWrongFormat = true;
                throw new System.Exception();
            }
            //read rest of file.
            SuccessfulFileReadEventHandler(this,null);
        }
        catch
        {
            if (isWrongFormat)
                MessageBox.Show("Wrong format.");
            else
                MessageBox.Show("Couldn't access.");
            ErrorInFileReadEventHandler(this, null);
            return;
        }
        finally
        {
            this.Dispose();
        }
    }
}

它是这样使用的:

class MyClass
{
    internal filePath; //assuming it has already been determined

    internal ImageData(string filePath)
    {
        this.filePath = filePath;
        OpenFileService ofs = new OpenFileService();
        ofs.ErrorInFileReadEventHandler += new EventHandler(UnsuccessfulFileRead);
        ofs.SuccessfulFileReadEventHandler += new EventHandler(SuccessfulFileRead);
        Thread thread = new Thread(new ParameterizedThreadStart(ofs.OpenFile));
        thread.IsBackground = true;
        thread.Start(this);
    }
}

现在当文件格式错误并且我自己在try 块中创建异常时,一切正常,但当文件实际上无法访问(例如写保护)br.Dispose(); 创建一个@ 987654330@ 我不知道为什么。 我真的把代码精简到了最基本的部分,我希望它不会太长。

编辑:可以从已接受的答案here 作为微软推荐的答案中找到可能的答案。

【问题讨论】:

  • 可能 br 保持为空,因为文件被写保护?
  • 哇...我真的错过了这个想法。用if(br != null) br.Dispose(); 替换br.Dispose(); 似乎可以解决它......非常感谢!我不敢相信我怎么没想到这一点。
  • 欢迎您。任何人都可能发生。

标签: c# nullreferenceexception idisposable binaryreader


【解决方案1】:

如果您将文件打开逻辑分成两行,问题可能会变得更清楚:

try
{
    var fs = File.Open((sender).fileName, FileMode.Open);
    br = new BinaryReader(fs);
}
finally
{
    br.Dispose();
}

File.Open 调用失败时,会抛出异常,而不会为br 字段分配任何内容。当您尝试在 finally 块中处理它时,它仍然是 null,因此您的例外。

编辑:我建议的解决方法:

try
{
    using (FileStream fs = File.Open(sender.fileName, FileMode.Open))
    using (BinaryReader br = new BinaryReader(fs))
    {        
        //read in header from file.
        if ( /*header shows wrong file format*/ )
        {     
            isWrongFormat = true;
            MessageBox.Show("Wrong format.");
            ErrorInFileReadEventHandler(this, null);
        }
        else
        {
            //read rest of file.
            SuccessfulFileReadEventHandler(this, null);
        }
    }
}
catch
{
    MessageBox.Show("Couldn't access.");
    ErrorInFileReadEventHandler(this, null);
}

在此过程中,我已将您的 BinaryReader 从字段降级为局部变量。由于您仅在 OpenFile 方法中访问它(并在返回之前将其处理掉),因此无需将其引用保留在方法之外。

【讨论】:

  • 我接受这个答案,因为在对我的问题发表评论后,我意识到这是问题所在。谢谢你的回答,我会改的。我不必将 fs 作为非托管资源处理吗?
  • 一般来说,您应该处置您实例化的任何IDisposable 对象。但是,文件处理包装器是一个(不幸的)例外。 BinaryReader 类的 Dispose 方法还将关闭您在初始化期间传递给其构造函数的任何流。因此,简短的回答是否定的,只要您处置包装BinaryReader,您就不必处置文件流。
  • 好的,谢谢,我感觉微软会在他们的处理约定中添加一个令人困惑的例外。
  • 如果您需要详细说明,请参阅此答案(以及随后的讨论):Does disposing streamreader close the stream?
  • 我刚刚意识到您建议的答案可能行不通。如果 fs 抛出异常,br.Dispose(); 将在没有初始化的情况下被调用。
猜你喜欢
  • 1970-01-01
  • 2013-05-30
  • 1970-01-01
  • 2018-01-19
  • 1970-01-01
  • 2020-11-17
  • 2016-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多