1

I hope I described the problem correctly.

In the following code the drive.IsReady takes some time to complete. Prior to this is the command to print the text "Scanning drives..." in the textbox. The text though appears after the foreach() has completed.

Why is this happening and how can I notify the user prior to the long-running task?

public Form1()
{
    InitializeComponent();
    button1.Click += new System.EventHandler(this.Button1_Click);
}

private void Button1_Click(object sender, EventArgs e)
{
    richTextBox1.Text = "Scanning drives, please wait...";
    PopulateComboBox();
}

void PopulateComboBox()
{
    System.IO.DriveInfo[] drives = System.IO.DriveInfo.GetDrives();

    foreach (System.IO.DriveInfo drive in drives)
    {
        if (drive.IsReady)
        {
            comboBox1.Items.Add(drive.Name + drive.VolumeLabel);
        }
        else
        {
            comboBox1.Items.Add(drive.Name);
        }
    }            
}
NikosD
  • 125
  • 10
  • 2
    Your code is running on the gui message loop. Although you are adding to the combo boxes they won't repaint themselves until their paint message is delivered on the message loop, and that delivery won't happen until you return from your function. – Sean May 15 '19 at 14:35
  • 1
    Performing long running task in another thread will keep UI responsive. Look into `async/await`. You will have to [invoke](https://stackoverflow.com/a/661662/1997232) `comboBox1.Items.Add`. – Sinatr May 15 '19 at 14:39
  • @Sean Could you point me to documentation regarding the internal program flow. I know this is quite general but what would you suggest for a person like me to read? – NikosD May 16 '19 at 06:32

1 Answers1

1

These are the minimal changes required to make the slow part of your code (drive.IsReady) run asynchronously. It won't run faster, the intention is just to keep the UI responsive.

private async void Button1_Click(object sender, EventArgs e) // + async
{
    richTextBox1.Text = "Scanning drives, please wait...";
    await PopulateComboBox(); // + await
}

async Task PopulateComboBox() // async Task instead of void
{
    System.IO.DriveInfo[] drives = System.IO.DriveInfo.GetDrives();

    foreach (System.IO.DriveInfo drive in drives)
    {
        if (await Task.Run(() => drive.IsReady)) // + await Task.Run(() => ...)
        {
            comboBox1.Items.Add(drive.Name + drive.VolumeLabel);
        }
        else
        {
            comboBox1.Items.Add(drive.Name);
        }
    }            
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104