C# 这种行为是由于清理时垃圾收集的时间不可预测造成的吗?
当我更改列表中的选择时,对话框将更新,从列表中与该项关联的文件中读取。我通过使用下面代码中的C# 这种行为是由于清理时垃圾收集的时间不可预测造成的吗?,c#,wpf,C#,Wpf,当我更改列表中的选择时,对话框将更新,从列表中与该项关联的文件中读取。我通过使用下面代码中的using语句解决了这个问题 private void ViewModel_SelectedNoteChanged(object sender, EventArgs e) { try { contentRichTextBox.Document.Blocks.Clear(); if (VM.SelectedNo
using
语句解决了这个问题
private void ViewModel_SelectedNoteChanged(object sender, EventArgs e)
{
try
{
contentRichTextBox.Document.Blocks.Clear();
if (VM.SelectedNote != null)
{
if (!string.IsNullOrEmpty(VM.SelectedNote.FileLocation))
{
using (FileStream fileStream = new FileStream(VM.SelectedNote.FileLocation, FileMode.Open))
{
var contents = new TextRange(contentRichTextBox.Document.ContentStart, contentRichTextBox.Document.ContentEnd);
contents.Load(fileStream, DataFormats.Rtf);
}
}
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
如果我不使用上面的using
语句,那么它是命中还是未命中。有时它从文件中读取内容并显示它们,否则会引发异常
System.IO.IOException:'进程无法访问该文件
'D:\EClone\bin\Debug\netcoreapp3.1\3.rtf'
因为它正被另一个进程使用。”
我的问题是,为什么在没有使用
语句的情况下会出现不可预测的行为?是因为已知垃圾收集的不可预测性(当它决定清理时),还是因为我们永远无法确定垃圾收集何时清理文件?这是垃圾收集不确定性的一个好例子吗?还是其他原因?这正是由于不正确使用了IDisposable
和GC。
不使用使用
- 打开文件(并锁定它)并将引用存储在变量中
- 函数退出,但文件仍处于打开和锁定状态
- 如果GC在您再次尝试打开文件之前运行,则一切正常,因为在文件包装器的终结器中有一个关闭(和解锁)文件的代码
- 如果在GC运行之前尝试访问同一个文件,则会出现异常
在使用的情况下,您将通过调用Dispose
(使用using
将为您调用它)显式地关闭和解锁文件Dispose
将立即关闭并解锁文件,而无需等待GC,因此使用时,您的代码将始终按预期工作
此外,由于您无法控制GC何时运行,没有使用
的代码在设计上是不稳定的,因此即使它今天工作正常,明天也可能停止工作,因为系统有更多的可用内存(GC运行的频率不如今天),或者因为.net更新(有一些GC更改/改进)等等
因此,作为结论:如果您有实现IDisposable
的东西,当您不再需要该对象时(使用或手动),请始终调用Dispose
。只有在文档或指南中明确允许调用Dispose
(例如,对于Task
class)时,才可以省略调用Dispose
。当使用“using”语句时,它调用Dispose方法关闭文件流,我不知道它是否在终结器上关闭文件流。