BinaryReader 在被释放时抛出 NullReferenceException

本文关键字:NullReferenceException 释放 BinaryReader | 更新日期: 2023-09-27 18:31:19

我有一个类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();创建了一个NullReferenceException,我无法弄清楚为什么。我真的把代码精简到最基本的东西,我希望它不会太长。

编辑:可能的答案可以从接受的答案中找到 这里作为Microsoft推荐的答案。

BinaryReader 在被释放时抛出 NullReferenceException

如果将

文件打开逻辑拆分为两行,问题可能会变得更加清晰:

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 方法中访问它(并在返回之前释放它),因此无需将其引用保留在方法外部。