2016-12-28 6 views
0

Я пытаюсь добавить автоматизированные делеции в истекших надежный словарь объектов и, похоже, я должен реализовать свой собственный путь в соответствии с этим: https://stackoverflow.com/a/36466890/7293543автоматически истекают Service Fabric Надежный словарь объектов с помощью RunAsync

Мой подход заключается в использовании задача «RunAsync» и постоянно работает цикл while. Он работал в первые несколько раз, но я получаю странную ошибку, как только я добавил еще несколько объектов в словарь. Это глупый подход? Как другие люди автоматически очищают свои надежные словарные объекты?

protected override async Task RunAsync(CancellationToken cancellationToken) 
{ 
    while (true) 
    { 
     cancellationToken.ThrowIfCancellationRequested(); 
     await deleteExpired("MyDictionaryName", cancellationToken); 
    } 
} 

private async Task deleteExpired(string dictionaryName, CancellationToken cancellationToken) 
{ 
    var myDictionary = await this.StateManager.GetOrAddAsync<IReliableDictionary<string, CacheObject>>(dictionaryName); 
    Dictionary<string, CacheObject> ret = new Dictionary<string, CacheObject>(); 

    using (var tx = StateManager.CreateTransaction()) 
    { 
     var count = myDictionary.GetCountAsync(tx); 

     if (count.Result > 0) 
     { 
      IAsyncEnumerator<KeyValuePair<string, CacheObject>> e = (await myDictionary.CreateEnumerableAsync(tx)).GetAsyncEnumerator(); 

      while (await e.MoveNextAsync(cancellationToken)) 
      { 
       if (e.Current.Value.expiration <= DateTime.Now) 
       { 
        await myDictionary.TryRemoveAsync(tx, e.Current.Key); 
        await tx.CommitAsync(); 
        ServiceEventSource.Current.ServiceMessage(this.Context, String.Format("Object deleted at {0} - key: {1} expired at {2}", DateTime.Now.ToString(), e.Current.Key, e.Current.Value.expiration.ToString())); 
       } 
      } 
     } 
    } 
} 

Ошибка: ошибка происходит на «в то время (правда)» после того, как я добавил несколько надежных словаря объектов в моем словаре.

Помощник по удаленной обработке «FatalExecutionEngineError» обнаружил проблему в «C: \ SfDevCluster \ Data_App_Node_2 \ CacheApplicationType_App339 \ CachePkg.Code.1.0.0 \ Cache.exe».

Дополнительная информация: Время выполнения столкнулось с фатальной ошибкой. Адрес ошибки был равен 0x8c46ed90, на потоке 0x1980. Код ошибки: 0x80131623. Эта ошибка может быть ошибкой в ​​CLR или в небезопасных или не поддающихся проверке частях кода пользователя. Общие источники этой ошибки включают ошибки маршалинга пользователя для COM-interop или PInvoke, которые могут повредить стек.

+0

Я не вижу в вашем коде 'while (true)' и откуда вы знаете, что ошибка встречается в 'while (true)', когда она, по-видимому, является фатальной ошибкой в ​​вашем процессе, а не a. NET с трассировкой стека, которая позволяет вам понять, какая часть вашего кода не удалась? Я не думаю, что в вашем коде есть что-то, что может создать такую ​​ошибку, поэтому я предполагаю, что ошибка не связана с кодом, который вы опубликовали, или вы попали в ошибку в Service Fabric. –

+0

Не связано с ошибкой, но 1.'CommitAsync' должен быть после внутреннего цикла while (вы не можете использовать транзакцию после фиксации). 2. Добавьте некоторую задержку 'await Task.Delay (...)' после 'await deleteExpired..'. 3. Не рекомендуется смешивать операции с отдельными объектами и несколькими объектами с одной и той же транзакцией. –

+0

@MartinLiversage - «Пока (true)» находится в первой строке метода RunAsync. Я считаю, что ошибки возникают там, потому что там визуальная студия показывает ошибку (я приложу скриншот позже). – Jacky

ответ

2

Если надежный словарь содержит более одного элемента, готового к истечению срока действия, вышеуказанный код продолжает использовать транзакцию после ее прекращения (совершенного в вышеуказанном случае). Это вызывает утверждение в перечислении, поскольку оно используется после того, как транзакция, с которой она была связана, прекратилась.

Я буду обновлять эту рекомендацию в Reliable Collections к

  • Не следует использовать перечисление после операции, используемой для создания прекращается (совершено/прерванный) или утилизированы.
+0

Спасибо! Я переместил ожидание tx.CommitAsync() вне цикла while и добавил счетчик, чтобы он совершил транзакцию только в том случае, если счетчик больше 0 и после того, как он полностью выполнен со всеми TryRemoveAsync(). Я также добавил ожидание Task.Delay (60000) после ожидания deleteExpired («MyDictionaryName», cancelationToken). Это, казалось, решило проблему! – Jacky