我有一个类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的推荐答案。
答案 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
方法中访问它(并在返回之前处置它),因此不需要将其引用保留在方法之外。