【问题标题】:Avoiding Task Cancelled Exception in Azure DocumentDB in C#在 C# 中避免 Azure DocumentDB 中的任务取消异常
【发布时间】:2018-09-21 15:04:45
【问题描述】:

我们正在运行一个 Web 应用程序,它有多个线程通过单例类访问 Azure 的 DocumentDB API,以读取或写入数据到我们的 Cosmos 数据库。在这个类中,我们在静态构造函数中初始化我们的 DocumentClient。在整个程序中,多个线程可以访问数据库,调用如下方法(假设 Uri 是一个全局定义的属性):

    public static async Task SaveItem<T>(T item)
    {
        try
        {
            await Client.UpsertDocumentAsync(Uri, item);
        }
        catch (Exception)
        { 
          // Some Basic Exception Handling.
        }
     }

几乎每个方法都是异步的,我们从不对这些方法的调用者调用 .Wait 或 .Result 。问题是,从多个线程中保存大量项目后,我们最终会得到以下异常:

System.Threading.Tasks.TaskCanceledException: A task was canceled.

这个异常特别奇怪的是,一旦第一次抛出,任何数据库调用(读取或写入)都不会成功,都会抛出同样的 TaskCancelledException。我们找到的唯一补救办法是重新启动程序。

抛出异常时的完整堆栈跟踪打印输出如下:

System.Threading.Tasks.TaskCanceledException: A task was canceled.
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.GatewayStoreModel.<>c__DisplayClass10.<<InvokeAsync>b__f>d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.BackoffRetryUtility`1.<>c__DisplayClass2.<<ExecuteAsync>b__0>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.BackoffRetryUtility`1.<ExecuteRetry>d__1b.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.Azure.Documents.BackoffRetryUtility`1.<ExecuteRetry>d__1b.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.BackoffRetryUtility`1.<ExecuteAsync>d__a.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.GatewayStoreModel.<InvokeAsync>d__1f.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.GatewayStoreModel.<ProcessMessageAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.Client.DocumentClient.<ReadAsync>d__30c.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.Client.DocumentClient.<ReadDocumentPrivateAsync>d__18d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.BackoffRetryUtility`1.<>c__DisplayClass2.<<ExecuteAsync>b__0>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.BackoffRetryUtility`1.<ExecuteRetry>d__1b.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.Azure.Documents.BackoffRetryUtility`1.<ExecuteRetry>d__1b.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.BackoffRetryUtility`1.<ExecuteAsync>d__a.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at AutomatedRegressionTestSuite.Managers.DatabaseManager.<GetItemAsync>d__20`1.MoveNext() in C:\Users\Administrator\Perforce\WinBuildServer\tools\Asriel\AutomatedRegressionTestSuite\Managers\DatabaseManager.cs:line 451
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at AutomatedRegressionTestSuite.Managers.DatabaseManager.<GetItemById>d__8`1.MoveNext() in C:\Users\Administrator\Perforce\WinBuildServer\tools\Asriel\AutomatedRegressionTestSuite\Managers\DatabaseManager.cs:line 104
   --- End of inner exception stack trace ---

我们如何防止这些任务取消异常的发生,或者至少以一种方式处理它们,使得我们的整个数据库在抛出后仍然可以访问?

【问题讨论】:

    标签: c# .net exception task azure-cosmosdb


    【解决方案1】:

    TaskCanceledException 来自 httpclient,这意味着它是一个 http 超时异常。请检查客户端的负载,负载上的异常短尖峰可能会导致此问题。否则,另一种选择是在 ConnectionPolicy 中提高 requestTimeout 以提供更多时间。

    【讨论】:

    • 感谢您的帮助。不幸的是,我们的要求需要一个异常的短暂峰值,然后是长时间的低吞吐量。我发现提高请求超时以及重试选项可以缓解问题。
    • 在使用 Azure DocumentClient 时如何增加 requestTimeout?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多