gpt4 book ai didi

c# - 使用 MEF 的线程安全延迟实例化

转载 作者:太空狗 更新时间:2023-10-30 01:26:33 24 4
gpt4 key购买 nike

// Member Variable
private static readonly object _syncLock = new object();

// Now inside a static method

foreach (var lazyObject in plugins)
{
if ((string)lazyObject.Metadata["key"] = "something")
{
lock (_syncLock)
{
// It seems the `IsValueCreated` is not up-to-date
if (!lazyObject.IsValueCreated)
lazyObject.value.DoSomething();
}
return lazyObject.value;
}
}

这里我需要每个循环的同步访问。有许多线程迭代此循环,并根据它们正在寻找的 key 创建并返回一个惰性实例。

lazyObject 不应创建多次。虽然 Lazy 类是为了这样做并且尽管使用了锁,但在高线程下我创建了多个实例(我用 Interlocked.Increment 跟踪这个 volatile static int 并将其记录在某处)。问题是我无权访问 Lazy 的定义,而 MEF 定义了 Lazy 类如何创建对象。我应该注意到 CompositionContainer 在已经使用的构造函数中有一个线程安全选项。

我的问题:

1) 为什么锁不起作用?

2) 我应该使用一组锁而不是一个锁来提高性能吗?

最佳答案

LazyT 的默认构造函数是否复杂? MEF 使用 LazyThreadSafetyMode.PublicationOnly 这意味着每个访问单元化 Lazy 的线程都会在 T 上生成一个 new() 直到第一个完成初始化。然后为当前访问 .Value 的所有线程返回该值,并且丢弃它们自己的 new() 实例。如果您的构造函数很复杂(也许做的太多?),您应该将其重新定义为进行最少的构造工作并将配置移至另一个方法。

您需要从整体上考虑该方法。您是否应该考虑:

public IPlugin GetPlugin(string key)
{
mutex.WaitOne();

try
{
var plugin = plugins
.Where(l => l.Metadata["key"] == key)
.Select(l => l.Value);
.FirstOrDefault();

return plugin;
}
finally
{
mutex.ReleaseMutex();
}
}

您还需要考虑,如果 plugins 不是只读的,那么您也需要同步对该实例的访问,否则它可能会在另一个线程上被修改,从而导致您的代码崩溃。

关于c# - 使用 MEF 的线程安全延迟实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4633634/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com