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

Time:12-12

The program asks a person if he wants to check the last closing price of Bitcoin and whenever he pushes the button it should first say "Loading..." and wait until the price is received and assign it to the .Text property of the label. When I run the code in a console app the application closes before actually receiving the needed information (writes only "Loading..." ) but if I add ReadKey() the price information shows up. I guess something similar happens to the windows forms app which tries to assign a missing value to the text property of value, hence the program crashes after displaying "Loading...".

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);
    }

CodePudding user response:

Why aren't you awaiting getAPI.ApiCall("[apikey]");? Using .Result before the task is completed, will result in a deadlock. The winforms has a SynchronizationContext set on that thread. Meaning that after the await, you're back on the UI thread and allowed and therefor able to modify UI-controls.

When you use .Result on a task, if it's not finished, it will wait there (block the thread). The problem is that when the task is ready, it will be posted on the UI thread, but never be executed, because the thread still blocked.

The difference between winforms and console. The console hasn't got a SynchronizationContext set, so the rest of the method (after the await) is posted on the threadpool. You're allowed to call Console.Writeline on anythread.

So use await here, so the thread isn't blocked.

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;
}

Here's some information:

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.


More about SynchronizationContext read codeproject.com Understanding-the-SynchronizationContext

  • Related