Fra*_*tin 22 c# idisposable using stream
我有一个方法,将FileStream作为输入.此方法在for循环内运行.
private void UploadFile(FileStream fileStream)
{
var stream = GetFileStream();
// do things with stream
}
Run Code Online (Sandbox Code Playgroud)
我有另一种方法,它创建并返回FileStream:
private FileStream GetFileStream()
{
using(FileStream fileStream = File.Open(myFile, FileMode.Open))
{
//Do something
return fileStream;
}
}
Run Code Online (Sandbox Code Playgroud)
现在第一个方法抛出一个ObjectDisposedException
当我尝试访问返回的FileStream时,可能是因为它已经关闭,因为我正在使用" using
"来正确处理流.
如果我不使用"using"而是按如下方式使用它,那么FileStream将保持打开状态,循环的下一次迭代(在同一文件上运行)会抛出异常,告知文件已在使用中:
private FileStream GetFileStream()
{
FileStream fileStream = File.Open(myFile, FileMode.Open);
//Do something
return fileStream;
}
Run Code Online (Sandbox Code Playgroud)
如果我使用try-finally块,我在那里关闭流,finally
那么它也会抛出ObjectDisposedException
.
如何有效地返回文件流并关闭它?
Dou*_*las 28
当您IDisposable
从方法返回时,您将把处理它的责任降级为您的调用者.因此,您需要using
围绕流的整个使用声明您的块,在您的情况下可能会跨越UploadFile
调用.
using (var s = GetFileStream())
UploadFile(s);
Run Code Online (Sandbox Code Playgroud)
Joe*_*orn 12
问题是,一旦退出GetFileStream()
方法,就会释放FileStream对象,使其处于不可用状态.正如其他答案已经指出的那样,您需要using
从该方法中删除块,而是将using
块放在调用此方法的任何代码周围:
private FileStream GetFileStream()
{
FileStream fileStream = File.Open(myFile, FileMode.Open);
//Do something
return fileStream;
}
using (var stream = GetFileStream())
{
UploadFile(stream);
}
Run Code Online (Sandbox Code Playgroud)
但是,我想更进一步.你想要一种方法来保护你创建的流,GetFileStream()
从一个草率的程序员可能在没有using
块的情况下调用方法的情况下,或者至少以某种方式向调用者强烈指示该方法的结果需要用using
块包围.因此,我建议这样:
public class FileIO : IDisposable
{
private FileStream streamResult = null;
public FileStream CreateFileStream(string myFile)
{
streamResult = File.Open(myFile, FileMode.Open);
//Do something
return streamResult;
}
public void Dispose()
{
if (streamResult != null) streamResult.Dispose();
}
}
using (var io = FileIO())
{
var stream = io.CreateFileStream(myFile);
// loop goes here.
}
Run Code Online (Sandbox Code Playgroud)
请注意,您不一定需要为此创建一个全新的类.您可能已经有一个适合此方法的类,您只需添加IDisposable代码即可.最重要的是,您可以将IDisposable
其代码应该用using
块包装作为其他程序员的信号.
此外,这会设置您修改类,以便您可以在循环之前创建一次IDisposable对象,并让新类实例跟踪在循环结束时需要处置的所有内容.