What is the wrong with following async/await example? Please guide [duplicate]

I have created a Windows Form - Form1, for understanding async-await in C#, and it has only two controls: a button (btnDemo) and a label (lblRandom). I am using .NET Framework 4.0.

This is the code:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private async void btnDemo_Click(object sender, EventArgs e)
    {
        Task<int> myTask = new Task<int>(GetNumber);
        myTask.Start();
        lblRandom.Text = "Getting...";
        lblRandom.Text = await myTask;
    }

    private int GetNumber()
    {
        Thread.Sleep(10000);
        return new Random().Next(1, 100);
    }
}

When I am trying to run this code, it shows me following error (on await myTask line):

'Task<int>' does not contain a definition for 'GetAwaiter' and no extension method 'GetAwaiter' accepting a first argument of type 'Task<int>' could be found (are you missing a using directive or an assembly reference?)

Can someone please help me understand this error and provide a solution for the above code?


This would probably be a better demonstration of async/await in winforms.. Make a new winforms project on .net framework 4.7.2 or .net 5+. On the default Form1 put a timer, two labels, two buttons and a datagridview on a form. Leave them all with their default names and paste this over the top of the form code:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        timer1.Enabled = true;
        timer1.Tick += Timer1_Tick;
        button1.Text = "ThreadSleep";
        button2.Text = "TaskDelay";
        dataGridView1.DataSource = new List<string[]> { "a b".Split(), "c d".Split()};
    }

    private void Timer1_Tick(object sender, EventArgs e)
    {
        label1.Text = DateTime.Now.ToString();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        label2.Text = "Going to sleep for 5s";
        Thread.Sleep(5000);
        label2.Text = "I'm awake";
    }

    private async void button2_Click(object sender, EventArgs e)
    {
        label2.Text = "Delaying for 5s";
        await Task.Delay(5000);
        label2.Text = "The task is done";
    }
}

Ensure you have these usings at the top:

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

Run the app. Click the ThreadSleep button and notice that the UI jams for 5 seconds; label2 doesn't update, the clock doesn't update, you cannot click in the datagridview and change the selection

This is because you sent the UI thread, whose job it is to draw the UI, to sleep for 5 seconds

Now click the TaskDelay button. Everything stays alive - the timer ticks up, the label2 says "delaying" instantly, you can still click around the DGV. This is because instead of sleeping the UI thread, async/await lets that thread stop running your code at the point it encounters await and go back to doing what it was doing before it started processing your code. When the task is done, it comes back and picks up where it left off