Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WebRequest挂起用户界面_C#_.net_Multithreading_Httpwebrequest - Fatal编程技术网

C# WebRequest挂起用户界面

C# WebRequest挂起用户界面,c#,.net,multithreading,httpwebrequest,C#,.net,Multithreading,Httpwebrequest,我正在用WebRequest执行简单的请求,应用程序只是挂起,直到响应返回。我该如何解决这个问题 我读过很多主题,他们都说使用线程。我不知道如何使用它们;有人能提供一个不挂起用户界面的以下示例吗 private string SimpleRequest(String url) { WebRequest request = WebRequest.Create(url); WebResponse response = request.GetResponse(); Stream

我正在用WebRequest执行简单的请求,应用程序只是挂起,直到响应返回。我该如何解决这个问题

我读过很多主题,他们都说使用线程。我不知道如何使用它们;有人能提供一个不挂起用户界面的以下示例吗

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");
}

谢谢

您正在主UI线程上进行网络访问。UI有一个主线程,用于循环和更新UI。如果您在该线程上进行网络访问,UI将不会更新,它将显示为挂起,直到您的方法返回并且循环可以继续

考虑在后台线程上进行工作。在.net中实现这一点的一个简单方法是BackgroundWorker类

官方文档中有一个很好的使用示例:

BackgroundWorker类允许您在服务器上运行操作 独立的、专用的线程。像下载这样耗时的操作 而数据库事务可能会导致用户界面(UI)看起来 就好像它在运行时停止了响应。当你 想要一个响应迅速的用户界面,您将面临与之相关的长时间延迟 通过这些操作,BackgroundWorker类提供了一个方便的 解决方案


您可以使用
BackgroundWorker
来使用UI线程以外的其他线程

您还可以取消或显示进度:

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");
    }
}
如果你使用的是c#5.0,那就太简单了

public async void Test1()
{
      WebClient wc = new WebClient();
      richTextBox1.Text =  await wc.DownloadStringTaskAsync("https://facebook.com");
}
您还可以将您的方法转换为
等待

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;
        });
}
有关C#的较低版本,请参阅其他答案。

您应该使用a,这样您的主UI线程就不会挂起


您也可以实现backgroundWorker1\u ProgressChanged,以便用户可以看到加载网站的进度。(旁注:有关详细信息,请参见此问题)

您将使用e.result.ToString()获得结果字符串,如我的示例中所示:D您可以自行决定如何处理它,请参见RunworkerComplete中的注释我尝试过输出它,但没有任何结果,它不会触发backgroundWorker1\u RunWorkerCompleted…也许您有错误,尝试显示任何错误消息-我将更新我的答案:((为什么它对我不起作用,这是完整的代码请检查更新您的代码以显示任何错误消息,如我更新的答案中所示-可能您的防火墙被阻止或任何其他-MessageBox.show(e.error.message);顺便提一下,如果我想在for循环中使用它,我只需添加循环线程。Sleep(100);?如果你想进行许多查询(许多调用simpleRequest)在不等待完成的情况下,您可以对simpleRequest进行异步调用,但如果您想让许多调用等待完成,您可以使用回调来获得完成,并在这一次中启动另一个simpleRequest调用(使用线程等待。在特定时间睡眠是一个好方法;-)tanks是最佳答案
public async void Test2()
{
      richTextBox1.Text =  await simpleRequest("https://facebook.com");
}
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
}