user1558223
user1558223

Reputation: 197

WebRequest hangs user interface

I'm doing simple request with WebRequest and the app just hangs until the response comes back. How do I fix this?

I have read a lot of topics and they all say to use threads. I don't know how to use them; can anyone provide an example of the following that doesn't hang the user interface?

private string SimpleRequest(String url)
{
    WebRequest request = WebRequest.Create(url);
    WebResponse response = request.GetResponse();
    Stream stream = response.GetResponseStream();
    StreamReader reader = new StreamReader(stream);
    string result = reader.ReadToEnd();
    stream.Dispose();
    reader.Dispose();
    return result;
}

private void button1_Click(object sender, EventArgs e)
{
    String googleHtml = simpleRequest("https://facebook.com");
}

Thanks!

Upvotes: 2

Views: 3222

Answers (4)

Hassan Boutougha
Hassan Boutougha

Reputation: 3919

You can use a BackgroundWorker in order to use another thread than UI thread. Here is a sample.

You can also cancel or display progress:

public partial class fmMain : Form
{
    private void btnrunBackgroundWorker_Click( object sender, EventArgs e )
    {
        // Create a background worker
        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += new DoWorkEventHandler( bw_DoWork );

        // run in another thread
        bw.RunWorkerAsync();     
    }

    private void bw_DoWork( object sender, DoWorkEventArgs e )
    {
        String facebookHtml = simpleRequest("https://facebook.com");
    }
}

Upvotes: 3

Pilgerstorfer Franz
Pilgerstorfer Franz

Reputation: 8359

You should use a BackgroundWorker so your main UI thread does not hang!

private void button1_Click(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync("https://facebook.com"); // start async operation
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    e.Result = simpleRequest(e.Argument.ToString()); // set result in async operation
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error == null)
    {
        // show result here
        // or access/manage result here
        MessageBox.Show(e.Result.ToString());
    }
    else
    {
        // manage/show error
        MessageBox.Show(e.Error.Message);
    }
}
private String simpleRequest(String url)
{
     // your code goes here
}

You could implement backgroundWorker1_ProgressChanged too, so that the user can see progress of loading webSite. (sideNote: see this question for details on ProgressChanged and Context)

Upvotes: 2

L.B
L.B

Reputation: 116188

If you are using c# 5.0 it is too easy

public async void Test1()
{
      WebClient wc = new WebClient();
      richTextBox1.Text =  await wc.DownloadStringTaskAsync("https://facebook.com");
}

You can convert your method to awaitable also

private Task<string> simpleRequest(String url)
{
    return Task.Factory.StartNew(() =>
        {
            WebRequest request = WebRequest.Create(url);
            WebResponse response = request.GetResponse();
            Stream stream = response.GetResponseStream();
            StreamReader reader = new StreamReader(stream);
            string result = reader.ReadToEnd();
            stream.Dispose();
            reader.Dispose();
            return result;
        });
}

and call as

public async void Test2()
{
      richTextBox1.Text =  await simpleRequest("https://facebook.com");
}

For lower versions of C#, See other answers.

Upvotes: 8

bryanmac
bryanmac

Reputation: 39306

You're doing network access on the main UI thread. The UI has a main thread which loops and updates the UI. If you do network access on that thread, the UI will not update and it will appear hung until your method returns and the loop can continue.

Consider doing your work on a background thread. One easy way to do that in .net is the BackgroundWorker class.

The official documentation has a nice example of it's usage:

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

The BackgroundWorker class allows you to run an operation on a separate, dedicated thread. Time-consuming operations like downloads and database transactions can cause your user interface (UI) to seem as though it has stopped responding while they are running. When you want a responsive UI and you are faced with long delays associated with such operations, the BackgroundWorker class provides a convenient solution.

Upvotes: 3

Related Questions