Корректная инициализация ReliableCollection из StateManager - PullRequest
0 голосов
/ 29 ноября 2018

Есть ли у кого-нибудь понимание того, какой из следующих двух псевдо-шаблонов является правильным способом создания экземпляров / использования надежных коллекций внутри службы фабрики состояний с сохранением состояния?В частности, интересно, является ли один подход более производительным, более ресурсоемким или даже более подверженным ошибкам.

Подход 1 (получить экземпляр из StateManager внутри метода):

public class MyService : IService {

  public async Task<string> GetSomeValueAsync(string input){
    var reliableDic = await StateManager.GetOrAddAsync<IReliableDictionary<string, string>>(StateKey);
    var result = await reliableDic.TryGetValue(input);
    return result.HasValue ? result.Value : null;
  }
}

Подход 2 (сохранитьколлекция как переменная-член класса)

public class MyService : IService {
  private bool _isInitialized;
  private readonly object _lock = new object();
  private IReliableDictionary<string, string> _dictionary;

  private async Task Initialize(){
     if (_isInitialized){
       return;
     }

     lock(_lock){
       if (_isInitialized){
         return;
       }

       _dictionary = await StateManager.GetOrAddAsync<IReliableDictionary<string, string>>(StateKey);
       _isInitialized = true;
     }
  }     

  public async Task<string> GetSomeValueAsync(string input){
    await Initialize();
    var result = await _dictionary.TryGetValue(input);
    return result.HasValue ? result.Value : null;
  }
}

Итак, подход 1 выбирает словарь из StateManager в каждом методе, в то время как подход 2 выполняет ленивую проверку инициализации и затем использует члены класса.

Большинствопримеры, которые мы видим, используют подход 1, но идея подхода 2 заключается в том, чтобы сохранить надежный словарь в поле экземпляра и избежать любого попадания StateManager.GetOrAddAsync в каждом методе, а также централизовать обработку StateKey, которая может быть полезна вболее крупные сервисы со многими методами и потенциально более надежными коллекциями.

Хотелось бы узнать, есть ли какие-либо подводные камни или недостатки в любом подходе (очевидно, подход 2 более многословен и использует больше строк кода, но это непервоочередная задача).

1 Ответ

0 голосов
/ 30 ноября 2018

На самом деле нет никакой реальной причины кешировать результат StateManager.GetOrAddAsync, за исключением сохранения выделения памяти для объекта Task или его доступности в местах, где StateManager недоступно.

Причина этого довольно проста - StateManager уже кеширует экземпляр IRealiableState для вас.Поэтому он возвращает один и тот же экземпляр каждый раз, когда вы делаете StateManager.GetOrAddAsync ( здесь - официальный ответ от Microsoft).

Вы также можете проверить его самостоятельно с помощью очень простого теста (c is true):

var q1 = stateManager.GetOrAddAsync<IReliableDictionary<string, string>>("MyDict")
                     .GetAwaiter().GetResult();
var q2 = stateManager.GetOrAddAsync<IReliableDictionary<string, string>>("MyDict")
                     .GetAwaiter().GetResult();
var c = q1 == q2;
...