如何等待 return 响应以分配给 C# 中标签的 .Text 属性

How to await the return response in order to assign to the .Text property of a label in C#

该程序询问一个人是否要检查比特币的最后收盘价,每当他按下按钮时,它应该首先说“正在加载...”,然后等到收到价格并将其分配给 .标签的文本 属性。当我 运行 控制台应用程序中的代码时,应用程序在实际接收到所需信息之前关闭(只写“正在加载...”)但是如果我添加 ReadKey() 价格信息就会显示出来。我想 windows 表单应用程序会发生类似的事情,它试图将缺失值分配给值的文本 属性,因此程序在显示“正在加载...”后崩溃。

public static async Task<string> ApiCall(string apikey)
    {
        RestClient client = new RestClient("https://api.polygon.io/v2/aggs/ticker/X:BTCUSD/prev?adjusted=true&apiKey=");//write your api key
        RestRequest request = new RestRequest($"?api-key={apikey}", Method.GET);
        IRestResponse response = await client.ExecuteAsync(request);
        return response.Content;
    }

    public static async Task<string> apiReceiver(string last_closed)
    {
        Task<string> apiCallTask = getAPI.ApiCall("[apikey]");
        string result = apiCallTask.Result;
        dynamic array = JsonConvert.DeserializeObject(result);
        last_closed = array.results[0].c;
        return last_closed;
    }

    public static async Task dataWait(Label lab, string last_closed)
    {
        lab.Text = "Loading info ...";
        lab.Text = await apiReceiver(last_closed);

    } 

    private async void button1_Click(object sender, EventArgs e)
    {
        string last_closed = "";
        await getAPI.dataWait(label1, last_closed);
    }

你为什么不等待 getAPI.ApiCall("[apikey]");?在任务完成之前使用 .Result 将导致死锁。 winforms 在该线程上设置了 SynchronizationContext。这意味着在等待之后,您将回到 UI 线程并允许并因此能够修改 UI-controls.

当你在一个任务上使用.Result时,如果它没有完成,它会在那里等待(阻塞线程)。问题是当任务就绪时,它会被发布到UI线程,但永远不会被执行,因为线程仍然阻塞。

winforms和console的区别。控制台没有设置 SynchronizationContext,因此该方法的其余部分(在 await 之后)发布在线程池上。您可以在任何线程上调用 Console.Writeline

所以这里使用await,这样线程就不会阻塞了。

public static async Task<string> apiReceiver(string last_closed)
{
    string result = await getAPI.ApiCall("[apikey]");
    dynamic array = JsonConvert.DeserializeObject(result);
    last_closed = array.results[0].c;
    return last_closed;
}

这里有一些信息:

source

However, if that code is run in a UI Application, for example when a button is clicked like in the following example: Then the application will freeze and stop working, we have a deadlock. Of course, users of our library will complain because it makes the application unresponsive.


阅读有关 SynchronizationContext 的更多信息codeproject.com Understanding-the-SynchronizationContext