jacobz
jacobz

Reputation: 3291

BackgroundWorker with Webclient downloadstring

So basically I want to retrieve the content of a .txt file on the internet and write it into a a label. However though, while it does this Windows Forms freezes.

So I thought of putting it into a BackgroundWorker. There is also a progress bar which should be filled during the progress. My code looks like this:

private void RetrieveTxt(string currentversion)
    {
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    }

void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        WebClient wc = new WebClient();
        label1.Text = wc.DownloadString("http://example.org/version.txt");
    }

void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        updateProgress.Value = e.ProgressPercentage;
    }

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        updateProgress.Visible = false;
    }

However though, it doesn't work; the label never gets updated and the progress bar stays empty.

Any help is appreciated, thank you! :)

Upvotes: 0

Views: 2949

Answers (2)

Servy
Servy

Reputation: 203837

If you're using C# 5.0 you can do the following:

label1.Text = await client.DownloadStringTaskAsync("http://example.org/version.txt");

It's just that easy.

If you're not, then you can leverage the async support of WebClient; you don't need to use a BackgroundWorker:

WebClient client = new WebClient();
client.DownloadStringCompleted += (s, data) =>
{
    label1.Invoke(new Action(() => label1.Text = data.Result));
};
client.DownloadStringAsync(new Uri("http://example.org/version.txt"));

As for why your code doesn't work:

  1. You never actually started the worker. You never called worker.RunWorkerAsync();
  2. You're accessing a UI control from a background task, so it will just break when you try to access the label from the DoWork handler. You would need to set the result to be the string that the WebClient returns and then set the label in the completed handler.

Upvotes: 4

DonBoitnott
DonBoitnott

Reputation: 11025

You need a delegate because the background thread can't operate on UI controls:

private delegate void InvokeUpdateText(String theText);
private void UpdateText(String theText)
{
    if (InvokeRequired)
    {
        try { Invoke(new InvokeUpdateText(UpdateText), theText); }
        catch { }
        return;
    }
    label1.Text = theText;
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    WebClient wc = new WebClient();
    UpdateText("http://example.org/version.txt");
}

Upvotes: 1

Related Questions