Здравствуйте, Слава, Вы писали:
С>Пока что я себе это представляю, как возврат некоего Task, который создаётся только одним запросом, а все остальные им пользуются, ожидая завершения. Или можно сделать некий выделенный тред с машиной состояний и очередью запросов вида "верни значение по ключу", который будет отвечать либо значением, либо ошибкой, либо будет держать запрос в очереди, пока словарь не обновится.
https://blogs.msdn.microsoft.com/fkaduk/2018/09/02/multiple-ways-how-to-limit-parallel-tasks-processing/... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Не проще сделать отдельный тред, который будет обновлять словарь раз в t минут/секунд?
Тогда можно считать, что данные в словаре всегда актуальны и либо возвращать найденное, либо выдавать 500.
Из минусов — потенциально большее количество запросов к стороннему сервису.
Из плюсов — элементарная реализация, не требующая никакой синхронизации доступа к словарю.
Типа такого:
public class AutoUpdateCache<TKey, TValue> : IDisposable
{
private readonly Func<IDictionary<TKey, TValue>> m_DataLoader;
private readonly Task m_SyncTask;
private readonly ManualResetEvent m_DisposingEvent;
private volatile IDictionary<TKey, TValue> m_Inner;
private readonly TimeSpan m_SyncPeriod;
public AutoUpdateCache(Func<IDictionary<TKey, TValue>> dataLoader, TimeSpan? syncPeriod = null)
{
m_DataLoader = dataLoader ?? throw new ArgumentNullException(nameof(dataLoader));
m_SyncPeriod = syncPeriod ?? TimeSpan.FromSeconds(5);
m_Inner = new Dictionary<TKey, TValue>();
m_DisposingEvent = new ManualResetEvent(false);
m_SyncTask = Task.Factory.StartNew(syncRoutine, TaskCreationOptions.LongRunning);
}
public TValue GetItem(TKey key)
{
return m_Inner.TryGetValue(key, out var value) ? value : default(TValue);
}
public void Dispose()
{
if (m_DisposingEvent.WaitOne(1)) throw new ObjectDisposedException(nameof(AutoUpdateCache<TKey, TValue>));
m_DisposingEvent.Set();
m_SyncTask.Wait();
m_SyncTask.Dispose();
m_DisposingEvent.Dispose();
}
private void syncRoutine()
{
do
{
m_Inner = m_DataLoader(); // Atomic volatile write of the reference variable
}
while (!m_DisposingEvent.WaitOne(m_SyncPeriod))
}
}
Здравствуйте, Слава, Вы писали:
С>ASP.NET Core
С>Есть некий большой словарь, который берётся из стороннего вебсервиса.
С>Когда в ходе обработки запроса требуется найти ключ в этом словаре, можно поискать ключ, а если не нашёлся — то обновить словарь, обратившись к вебсервису. Если же и после этого не нашёлся — значит, есть несогласованность в данных возвращаем 500. Если словарь обновлялся меньше, чем t времени назад, то можно сразу возвращать 500, не обновляя его.
Это похоже на
https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern — там есть ссылка внизу на пример использования библиотеки Polly для этого.