2016-12-28 48 views
0

我想自动删除添加到过期可靠的字典对象自动终止服务织物可靠的Dictionary对象,它看起来像我根据这个来实现我自己的方式:https://stackoverflow.com/a/36466890/7293543通过RunAsync

我的方法是使用“RunAsync”任务并让它不断运行一段时间循环。它在前几次都有效,但当我向我的字典中添加了更多的对象时,我收到了一个奇怪的错误。这是一个愚蠢的做法吗?其他人如何自动清除其可靠的字典对象?

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异常,可以让你理解代码失败的部分?我认为你的代码中没有任何东西可以产生这样的错误,所以我的猜测是错误与你发布的代码无关,或者你在服务结构中遇到了一个错误。 –

+0

与错误无关,但1.CommitAsync应该在inner while循环之后(在提交之后不能使用事务)。 2.在'等待deleteExpired..'后添加一些延迟'await Task.Delay(...)'。 3.建议不要将单个实体和多个实体操作混合在同一个事务中。 –

+0

@MartinLiversage - “While(true)”在RunAsync方法的第一行。我相信错误发生在那里,因为那是Visual Studio显示错误的地方(我将在后面添加屏幕截图)。 – Jacky

回答

2

如果Reliable Dictionary包含多个准备过期的项目,则上述代码在终止(在上述情况下提交)后继续使用该事务。这会导致枚举中的断言,因为它在被绑定的事务终止之后被使用。

我将更新Reliable Collections

  • 建议用于创建被终止交易后不要使用枚举(致力于/中止)或设置。
+0

谢谢!我在while循环之外移动了await tx.CommitAsync()并添加了一个计数器,以便只在计数器大于0并且完全使用TryRemoveAsync()完成后才提交事务。在等待deleteExpired(“MyDictionaryName”,cancellationToken)后,我还添加了一个await Task.Delay(60000)。 这似乎解决了这个问题! – Jacky