Код ниже будет вызываться с веб-сайта, поэтому наличие статического словарного объекта в нестатическом классе должно быть поточно-ориентированным.По сути, целью кода является инкапсуляция логики и сохранение времени жизни счетчика (ов) perfmon, которые хранятся в экземпляре CounterContainer.Конструктор называется передачей в instanceName.Конструктор должен проверить, был ли CounterContainer для этого instanceName определен и сохранен в словаре.Если это так, он может (и должен) использовать этот экземпляр.Если нет, то он создает экземпляр CounterContainer, сохраняет его в словаре и затем использует этот экземпляр.Используемый экземпляр CounterContainer хранится в нестатическом члене, поэтому с этого момента он безопасен для потоков.
Поскольку единственное место, в котором используется статический словарь, находится внутри конструктора, мне кажется, чтобудет безопасно заблокировать словарь на время доступа к нему?Будет ли это позже вызывать какие-либо непредвиденные проблемы с блокировкой / взаимоблокировкой?Я ничего не вижу, но в прошлом мне не приходилось слишком много думать об этом.
Я также рассмотрел lock (this): , но я не думаю, что это сработало бы, так как это блокировало бы только создаваемый экземпляр PerformanceCounters, а не базовый статический словарь (такне будет потокобезопасным).
namespace ToolKit
{
using System;
using System.Diagnostics;
using System.Collections.Generic;
public class PerformanceCounters : IPerformanceCounters
{
private static Dictionary<string, CounterContainer> _containers = new Dictionary<string, CounterContainer>();
private CounterContainer _instanceContainer;
public PerformanceCounters(string instanceName)
{
if (instanceName == null) throw new ArgumentNullException("instanceName");
if (string.IsNullOrWhiteSpace(instanceName)) throw new ArgumentException("instanceName");
// Is this the best item to lock on?
lock (_containers)
{
if (_containers.ContainsKey(instanceName))
{
_instanceContainer = _containers[instanceName];
return;
}
_instanceContainer = new CounterContainer(instanceName);
_containers.Add(instanceName, _instanceContainer);
}
}
public void Start()
{
_instanceContainer.AvgSearchDuration.Start();
}
public void FinishAndLog()
{
_instanceContainer.SearchesExecuted.Increment();
_instanceContainer.SearchesPerSecond.Increment();
_instanceContainer.AvgSearchDuration.Increment();
}
}
}