c# - 当 API 返回 "too many requests"错误时,在 C# 中多次重试同一任务

标签 c# .net asynchronous throttling http-status-code-429

我有一个通用方法可以在同步上下文中通过重试执行异步任务。

public static T RunWithRetries<T>(Task<T> task)
{
   while(...) // 3 attempts
   {
       try 
       {
          task.GetAwaiter().GetResult();
       }
       catch 
       {
         // sleep & retry later in case of some exceptions, for example 429
       }
   }
}

然后我从异步 API 传递任何方法来运行它。

SyncHelper.RunWithRetries(externalAPI.UploadAsync(fileRequest, fileStream));

问题是除非在请求期间发生异常并且我们需要重试,否则它可以正常工作。如果发生错误,所有后续重试也会抛出相同的异常。所以,我的问题是

  1. 发生这种情况是因为 fileStream 对象吗?它在 using 语句中,所以它肯定不会被处理掉。第一次上传尝试后的流位置会不会有问题?
  2. 重试同一个任务对象是否正常?我是否应该改变我做这件事的方式来做更好的事情?

最佳答案

Is this happening because of the fileStream object? It's in the using statement, so it's not being disposed for sure. Can the stream position after first upload attempt be a problem?

是的,这是您的问题之一。每当读取流时,它的 Position不会自动重置为 0。如果您尝试重新读取它,那么它不会读取任何内容,因为该位置位于流的末尾。

因此,您必须每次都创建一个新流,或者 rewind the stream to the beginning .

Is it normal that the same Task object is being retried? Should I change the way I'm doing it to something better?

每当任务完成时(有特定结果或异常),然后重新 await -ing 或检索其 Result不会触发重新执行。它将简单地返回值或异常。

因此,您必须为每次重试尝试创建一个新任务。为此,您可以预期 Func<Task<T>>在你的RunWithRetries

public static T RunWithRetries<T>(Func<Task<T>> issueRequest)
{
    ...
    issueRequest().GetAwaiter().GetResult();

}

从调用方来看,它看起来像这样:

RunWithRetries(() => externalAPI.UploadAsync(fileRequest, new FileStream(...)));
//or
RunWithRetries(() => { fileStream.Position = 0; externalAPI.UploadAsync(fileRequest, fileStream); });

关于c# - 当 API 返回 "too many requests"错误时,在 C# 中多次重试同一任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70122701/

相关文章:

asp.net - 是否使用 TPL 或 async/await

javascript - 浏览器中的异步 XMLHttpRequest 阻塞 UI

c# - 使用 dapper c# 填充列表对象

c# - 内部元素数量不变的 LINQ.SelectMany 的替代品

c# - Windows 8 应用程序中的屏幕分辨率检测

.net - 使用 WebDeploy (MSDeploy) 部署到 Microsoft Azure 网站目标不起作用

javascript - Node.js 中的异步困惑

c# - 在子查询上使用 DISTINCT 以删除 Entity Framework 中的重复项

.net - 当我遍历字典(.NET通用数据结构)时,它的顺序是否与添加它们的顺序相同?

Automapper 表达式必须解析为顶级成员