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:
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