0

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

代码应该是什么才能始终如一地从 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 只是一个断点,所以我可以评估哪种反序列化尝试效果最好,我还没有看到有人停下来。

4

1 回答 1

2

如果运行以下代码:

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");也没有被打印出来!并且返回值也不会被打印出来!

那么这里发生了什么?仅仅因为该方法被定义为异步并且其中有一个等待并不意味着调用者可以保证异步执行! 具体来说,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 内部正确等待,执行返回给调用者,现在可以自由地继续执行其他任务,例如更新 GUI(在这个简单的控制台应用程序中不是这种情况)。希望这能说明这里发生了什么,基本上调用者,在这种情况下Main,也需要等待异步GetProductAsync方法的结果才能看到结果。

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

于 2020-10-07T22:00:42.973 回答