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方法关闭文件流,我不知道它是否在终结器上关闭文件流。