带有 await GetAsync API 调用的方法在没有返回结果或 运行 方法中的所有代码的情况下退出

Method with await GetAsync API call exits without a returning a result or running all code in the method

借鉴https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client中的Get方法,我写了以下内容。作为 C# 的新手,我假设 await 会完成 API 调用然后继续,但是发生的事情是该行执行然后退出方法而没有 运行 另一行代码(if 语句,return).我可能也假设了其他事情,这让我陷入了这种困境。

代码应该是什么才能始终从 API 调用中获得响应并反序列化 Json 以便我可以检索我实际需要的 2 位数据?

对我的代码提出的任何其他改进建议也非常感谢。

方法调用: var ReturnedData = GetProductAsync(companyCode);

方法:

//API Call method - https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client
static HttpClient client = new HttpClient();
static async Task<ReturnedAPIdata> GetProductAsync(string CoCode)
{
    // TODO - This key will need to be taken out of the code and put in a config file or something
    string DavesKey = "abc123";
    string path = "http://api.marketstack.com/v1/eod?access_key=" + DavesKey + "&symbols=" + CoCode + ".XASX&sort=DESC&limit=1&offset=0";

    ReturnedAPIdata ThatAPIdata = null;
    HttpResponseMessage response = await client.GetAsync(path);
    response.EnsureSuccessStatusCode();

    if (response.IsSuccessStatusCode)
    {
        // If we have an API response, deserialise the Json data... somehow
        //ThatAPIdata = await response.Content.ReadAsAsync<ReturnedAPIdata>();   // ReadAsAsync has been deprecated, but not replaced. Handy
        string responseBody = await response.Content.ReadAsStringAsync();
        // Which one of these fuckers actually works. Use an API, they said. It'll be fun, they said. ARG!
        ReturnedAPIdata Arses = System.Text.Json.JsonSerializer.Deserialize<ReturnedAPIdata>(responseBody); // attempt 3
        List<ReturnedAPIdata> Cock = JsonConvert.DeserializeObject<List<ReturnedAPIdata>>(responseBody);    // attempt 2
        ReturnedAPIdata Balls = JsonConvert.DeserializeObject<ReturnedAPIdata>(responseBody);               // attempt 1
    }
    Console.WriteLine("FFFFFFFFFfffff....");

    return ThatAPIdata;
}

最后的 Conrole.Writeline 只是一个断点,所以我可以评估哪种反序列化尝试效果最好,我还没有看到停止。

如果下面的代码是运行:

static void Main(string[] args)
{
    Console.WriteLine("Before calling async method");
    GetProductAsync();
    Console.WriteLine("After calling async method");
}

static async Task<string> GetProductAsync()
{
    await Task.Delay(5000);
    Console.WriteLine("Inside async method after await");
    return "Got all Products";
}

以下结果打印到控制台:

Before calling async method
System.Threading.Tasks.Task`1[System.String]
After calling async method

因此即使方法 GetProductAsync 被定义为 async 并且等待 5 秒,执行也会失败,还要注意在异步方法内部有一个 Console.WriteLine("Inside async method after await");这也不会被打印出来!而且 return 值也不会打印出来!

那么这里发生了什么?仅仅因为该方法被定义为 async 并且其中有一个 await 并不意味着调用者保证异步执行! 特别是调用它的 Main 方法没有 await 结果,所以这就是它失败的原因。

现在,如果代码已更改且 Main 正在等待 GetProductAsync 方法:

static async Task Main(string[] args)
{
    Console.WriteLine("Before calling async method");
    var result = await GetProductAsync();
    Console.WriteLine("After calling async method");
    Console.WriteLine(result);
}

static async Task<string> GetProductAsync()
{
    await Task.Delay(5000);
    Console.WriteLine("Inside async method after await");
    return "Got all Products";
}

现在打印到控制台的结果是:

Before calling async method
Inside async method after await
After calling async method
Got all Products

所以在这种情况下,在 main 内部正确等待结果,执行 return 给调用者 ,现在可以自由地继续执行其他任务,例如更新 GUI(在这个简单的控制台应用程序中不是这种情况)。 希望这说明了这里发生的事情,基本上调用者,在这种情况下 Main,也需要等待异步 GetProductAsync 方法的结果才能看到结果。

这篇文章很好地解释了各种陷阱和问题!无需深入 https://www.pluralsight.com/guides/understand-control-flow-async-await