0

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

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,我不知道为什么。我真的把代码精简到了最基本的部分,我希望它不会太长。

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

4

1 回答 1

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

于 2013-09-15T15:24:46.527 回答