递归异步/等待API调用

时间:2018-06-21 13:14:05

标签: c# recursion async-await

我有一个异步方法,可以对供应商进行API调用。供应商要求在发生错误的情况下,我们再打两次电话,并在电话中提供完全相同的信息。对于这种情况,我的第一个想法是使我的API方法递归。但是,在查看了本网站上的许多问题和其他文章之后,我很难理解异步/等待如何与递归一起工作。

我的方法(为演示而简化)如下。我不确定是否应该等待电话咨询? Visual Studio会引发标准的,因为未等待此调用,如果我不等待递归调用,将继续执行...等。当我确实等待递归调用时,它似乎确实起作用了,如果执行不正确,我只是担心要做什么。任何帮助将不胜感激。

public async Task<string> GetData(int UserID, int Retry = 0)
{
     try 
     {
         var Request = new HttpRequestMessage(HttpMethod.Post, "myurlhere");
         //Set other request info like headers and payload


         var Response = await WebClient.SendAsync(Request);             
         return await Response.Content.ReadAsStringAsync();         
     } 
     catch (Exception Ex)
     { 
          if (Retry <= 2)
          {
               Retry++;
               return await GetData(UserID, Retry); //Should I await this?
          }
          else 
          {
               return "";
          }
     }
 }

2 个答案:

答案 0 :(得分:1)

  

当我等待递归调用时,它确实可以工作,

太好了。

  

如果我做错了,我只是担心自己要做什么。

由于await导致Task不同步返回是由状态机处理的,因此与“正常”非正常情况相比,在这种情况下实际上减轻了堆栈负担-异步代码。递归调用成为另一个状态机,对其的引用是第一个状态机中的一个字段。

通常可以采用迭代而不是递归的方法(有一个循环并在首次成功时退出),但是实际上,即使非异步等效物也不会产生很大的堆栈压力,因此无需做任何不同的事情比你做的要好。

答案 1 :(得分:0)

这不是需要递归的情况。正如其他人所建议的那样,我会使用类似这样的东西:

public async Task<string> GetDataWithRetry(int UserID, int Tries = 1)
{
    Exception lastexception = null;

    for (int trycount=0; trycount < tries; trycount++)
        try
        {
            return await GetData(UserID);
        }
        catch (Exception Ex)
        {
            lastexception = Ex;
        }

    throw lastexception;
}

public async Task<string> GetData(int UserID)
{
     var Request = new HttpRequestMessage(HttpMethod.Post, "myurlhere");
     //Set other request info like headers and payload


     var Response = await WebClient.SendAsync(Request);             
     return await Response.Content.ReadAsStringAsync();         
}