处理时,BinaryReader会抛出NullReferenceException

时间:2013-09-15 15:05:27

标签: c# nullreferenceexception idisposable binaryreader

我有一个类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块中自己创建了异常时,一切都正常运行,但是当文件实际上无法被访问时(例如写保护){{1}创建一个br.Dispose();,我无法弄清楚为什么。 我真的把代码简化为基本要素,我希望它不会太长。

修改:可以从已接受的答案here中找到可能的答案作为Microsoft的推荐答案。

1 个答案:

答案 0 :(得分: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方法中访问它(并在返回之前处置它),因此不需要将其引用保留在方法之外。