【问题标题】:How can you use threading to send multiple web requests at a time in c#?如何在 C# 中使用线程一次发送多个 Web 请求?
【发布时间】:2013-07-24 10:56:27
【问题描述】:

我有一个简单的 ASP.NET 小程序,我正在尝试学习基本的多线程以使其运行更顺畅。

假设我有一个连接到以下方法的按钮:

private NlSearch search;

protected void SearchButtonClick(object sender, EventArgs e)
    {

        int resultCount = search.MakeRequests(SearchForm.Text);
        resultsLabel.Text += SearchForm.Text + ": " + resultCount.ToString() + "     occurances";
    }

MakeRequests 所做的只是发出一个 POST 请求以在 3rd 方网站上进行搜索,并从响应中获取结果数量。然后将搜索词与结果数量一起添加到页面中。

但是,如果我要在第一个搜索响应之前提交新搜索等操作,它只会中断原始搜索,并且只有最近的搜索会将其结果写入标签。

我知道有一种方法可以使用 C# 线程来执行此操作,但我无法弄清楚如何正确使用任务来执行此操作。我尝试将方法的主体放入不带参数的第二个方法中,然后我用它来创建和运行任务,但这并没有改变行为,所以我认为我错误地使用了任务。

任何帮助或建议将不胜感激,谢谢。

编辑:到目前为止我已经尝试过:这两个答案似乎都在检索值时“起作用”,但由于某种原因,由于某种原因,它们实际上都没有添加到标签中。例如

protected void NewSearchClick(object sender, EventArgs e)
    {
        new Thread(() => MakeRequest(SearchForm.Text)).Start();
    }

protected void MakeRequest(string text)
    {
            int resultCount = search.MakeRequests(text);
            if (resultsLabel != null) resultsLabel.Text += text + ": " + resultCount + "     occurances";
    }

似乎检索到了值,但标签没有改变。

【问题讨论】:

  • 线程 t = new Thread(new ThreadStart(YourMethod));?编辑:您也可以使用 ThreadPool 类。欲了解更多信息,请查看:msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx
  • 向我们展示您的尝试。基于此,我可能会告诉你该往哪个方向看。在深入研究任务之前,您可能需要先检查线程和线程池。
  • 为什么不禁用“搜索”按钮,直到收到第一个响应或超时?
  • @KappaG3 我不会尝试自己做这些事情,你可以快速运行线程池。 .NET 允许与任务进行托管并行。我会使用这种东西:msdn.microsoft.com/en-us/library/…
  • 看我最近的回答,你想用 Dispatcher 的线程,这样在任务运行时 UI 不会被阻塞,标签会得到更新

标签: c# multithreading http asynchronous web


【解决方案1】:

在 WPF 应用程序中,您应该同时使用线程和 Dispatcher,因为只有 UI 线程才能写入标签。更具体地说,当任务完成时,您应该使用调度程序作为回调来更新 UI 中的任何内容:

protected void SearchButtonClick(object sender, EventArgs e)
{
    new Thread(() => MakeRequest(SearchForm.Text)).Start();
}

protected void MakeRequest(string text)
{
    int resultCount = search.MakeRequests(text);

    // tell UI thread to update label
    Dispatcher.BeginInvoke(new Action(() =>
            {
                resultsLabel.Text += text + ": " + resultCount + "     occurances";
            }));
}

Edit1:使用 Dispatcher 而不仅仅是线程

Edit2:同时使用 Dispatcher 和线程

【讨论】:

  • 我已经尝试过这个和第一个答案,但由于某种原因,控制流甚至没有达到 MakeRequest。
  • 控制流是什么意思?这会启动一个新线程,因此如果您使用调试器单步执行点击 SearchButtonClick 的线程,它将不会到达 MakeRequest。你在用视觉工作室吗?
  • 是的。在视觉工作室。如果我使用了错误的术语,我对线程缺乏经验,很抱歉。我实际上弄错了,基于调试器似乎正在发生的事情是它正确检索 resultsCount 但没有将其写入 Label 出于某些原因。
  • 谢谢。它在静态上下文错误中生成了一个不能引用非静态方法,我做错了什么吗?
  • 产生该错误的原因是什么?你不应该需要任何静态的东西,也不应该看到那个错误
【解决方案2】:

我会使用 .NET Task,因为他们会为您管理线程池。

链接:Task [Managed parallelism]

protected void SearchButtonClick(object sender, EventArgs e)
{
   var text = SearchForm.Text;
   Task.Factory.StartNew(() => 
   {
      var resultCount = search.MakeRequests(text);
      resultsLabel.Text += text + ": " + resultCount + "     occurances";
   });
}

【讨论】:

  • 您需要在开始任务之前获取 SearchForm.Text,因为它可能会在任务运行之前更改
  • 我认为锁定局部变量没有意义!
  • 这在 WPF 应用程序中不起作用,只有 UI 线程可以更新 UI。
  • 哦,是的。我忘记了那条神奇的线。感谢您的澄清。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多