延迟初始化对象的线程安全处置

Hir*_*aka 8 .net c# thread-safety

在 C# 中处理延迟初始化对象的线程安全方法是什么?假设我有以下Lazy构造:

Lazy<MyClass> lazy = new Lazy<MyClass>(() => MyClass.Create(), true);
Run Code Online (Sandbox Code Playgroud)

稍后,我可能想处置MyClass创建的实例。大多数现有的解决方案都推荐这样的内容:

if (lazy.IsValueCreated)
{
    lazy.Value.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

但据我所知,IsValueCreated没有任何锁:https://referencesource.microsoft.com/#mscorlib/system/Lazy.cs,284

MyClass这意味着当我们检查 时,另一个线程可能正在初始化过程中IsValueCreated。在这种情况下,我们将观察IsValueCreated到错误,并最终泄漏资源。这里正确的做法是什么?还是我错过了一些微妙的细节?

Maz*_*eri 2

我会将我的惰性实例设置为 null ,Dispose()以便任何进一步的访问都会失败(例如 throwing ObjectDisposedException)。然后创建一个 getter 来处理这个问题:

MyClass MyObj => lazy?.Value ?? throw new ObjectDisposedException(nameof(MyObj));

public void Dispose()
{
   var lazyBeforeDispose = Interlocked.Exchange(ref lazy, null);
   if (lazyBeforeDispose?.IsValueCreated ?? false) 
   {
      lazyBeforeDispose.Value.Dispose();
   }
}
Run Code Online (Sandbox Code Playgroud)