.net 与“一致”的词典;“昂贵的”;价值
我有一个实现.net 与“一致”的词典;“昂贵的”;价值,.net,multithreading,performance,concurrency,concurrentdictionary,.net,Multithreading,Performance,Concurrency,Concurrentdictionary,我有一个实现async方法的多线程应用程序。应用程序通过RabbitMq进行通信,有时需要在IModel上执行代价高昂的操作(BasicConsume)。我有一个ConcurrentDictionary,其中保存了IModel(key)和IBasicConsumer(value),以避免与MessageBroker的额外往返 在启动时,多个执行会到达代码的同一部分,在该部分中查找使用者(值)是否存在。在前40种情况下,答案是否定的,但我不想做40BasicConsume,根据提供的IModel(
async
方法的多线程应用程序。应用程序通过RabbitMq进行通信,有时需要在IModel
上执行代价高昂的操作(BasicConsume
)。我有一个ConcurrentDictionary,其中保存了IModel
(key)和IBasicConsumer
(value),以避免与MessageBroker的额外往返
在启动时,多个执行会到达代码的同一部分,在该部分中查找使用者(值)是否存在。在前40种情况下,答案是否定的,但我不想做40BasicConsume
,根据提供的IModel
(键)只做一个或两个
使用lock
语句会导致不可接受的性能损失
目前,我正在解决以下问题
var consumerTcs = new TaskCompletionSouce<IBasicConsumer>();
if (_consumerDictionary.TryAdd(channel, consumerTcs))
{
var newConsumer = new EventingBasicConsumer(channel);
newConsumer.Model.BasicConsume(queue, false, newConsumer)
consumerTcs.TrySetResult(newConsumer);
return consumerTcs.Task;
}
else
{
return _consumerDictionary[channel].Task;
}
var consumerTcs=new TaskCompletionSouce();
if(_consumerDictionary.TryAdd(频道,consumerrtcs))
{
var newConsumer=新事件基本消费者(频道);
newConsumer.Model.BasicConsume(队列,false,newConsumer)
consumerTcs.TrySetResult(新消费者);
返回consumerTcs.Task;
}
其他的
{
返回_consumerDictionary[channel]。任务;
}
就是
TaskCompletionSource
(非expencive)作为字典的值TryAdd
,如果成功,则执行昂贵的操作TaskCompletionSource.Task
然而,我仍然创建了我不使用的
TaskCompletionSources
,这让我觉得有点难看。有什么建议可以帮助我解决这个问题,而不必使用锁
,也不必在创建未使用的对象时浪费时钟周期?您是如何衡量这个不可接受的性能影响的?另外,这也是GetOrAdd(TKey,Func)
的目的,使用它而不是TryAdd
和可能的争用条件,即如果您从字典中删除值,TryAdd
可能返回false
,但获取该值可能会通过使用嵌套任务运行代码抛出KeyNotFoundException
@acelent测量性能(20倍外部和50'000x内部)使用秒表。但是,GetOrAdd
可能就是我要找的!谢谢!GetOrAdd
不工作,因为将调用valueFactory
,直到valueFactory
返回其值。这会导致多个不必要的消息代理往返。您可以使用GetOrAdd
(使用Func
)为了避免创建许多TaskCompletionSouce
。它只不过是一个TryGet
,在没有值时可选地后跟一个TryAdd
,本质上是颠倒您当前的逻辑。如果有很多争用,最初可能会创建一些不必要的,但唯一能创建一个的方法是使用锁定块。唉,使用GetOrAdd
,除非设置捕获的变量,否则无法直接知道返回的对象是否是您创建的对象,因此手动TryGet
->TryAdd
更简单,并且执行相同的工作。