1

I have a button in my WinForms application with the following Click event:

    private void Button_Click(object sender, EventArgs e)
    {
        treasureFound = false;
        refreshNumber = 0;

        Label_StartDateTime.Text = DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss");
        while (!treasureFound)
        {
            Label_StatusData.Text = "Refreshed " + refreshNumber + " times.";
            refreshNumber++;
            using (WebClient client = new WebClient())
            {
                string htmlCode = client.DownloadString(webUrl);

                if (htmlCode.Contains("Treasure"))
                {
                    treasureFound = true;
                    Label_StatusData.Text = "Found.";
                    // etc etc
                }
            }
        }
    }

When the button is clicked, the UI thread locks up (not responding, labels don't update) until the while loop ends.

What can I do to keep the UI responsive? There should only be one WebClient instance at any one time.

ReignOfComputer
  • 747
  • 2
  • 10
  • 30
  • 3
    you should always move long blocking task to a different thread, one of the ways, is using [BackgroundWorker Class](https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.110).aspx) – styx Jun 20 '18 at 06:50
  • 2
    You should definitely use Threads e.g.: Like in this post: [Converting a WebClient method to async / await](https://stackoverflow.com/a/13240978/8916412) – bc291 Jun 20 '18 at 06:51
  • Thanks @needtobe, ended up using that. – ReignOfComputer Jun 20 '18 at 07:05
  • 1
    @needtobe DownloadStringTaskAsync in your link most likely doesn't use an extra thread, but just uses async IO. Tasks can be expressed by threads, but don't need to. – ckuri Jun 20 '18 at 07:14

1 Answers1

0

you should execute the time-consuming tasks in a separate thread, so it will not block the main thread (aka your UI thread). One way is to use the BackgroundWorker.

public Form1()
{
    InitializeComponent();

    backgroundWorker1.DoWork += backgroundWorker1_DoWork;
    backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
    backgroundWorker1.WorkerReportsProgress = true;
}

private void button1_Click(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    for (int i = 0; i < 100; i++)
    {
        Thread.Sleep(1000);
        backgroundWorker1.ReportProgress(i);
    }
}

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;
}

Taken from: How to use a BackgroundWorker?

Plexis Plexis
  • 302
  • 2
  • 12