【问题标题】:c# TimeOut all httpwebrequestsc# TimeOut all httpwebrequests
【发布时间】:2015-06-02 14:56:51
【问题描述】:

这不是关于如何中止线程猎点的问题。

我正在制作一个multi-threaded 程序,它在每个正在运行的线程中都有一个httpwebrequest,我想如果我想阻止所有这些线程中途他们正在做的事情,我必须让它们超时。 有没有办法在多线程的基础上做到这一点? 每个线程看起来像这样:

        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
        webRequest.Method = "GET";
        webRequest.Accept = "text/html";
        webRequest.AllowAutoRedirect = false;
        webRequest.Timeout = 1000 * 10;
        webRequest.ServicePoint.Expect100Continue = false;
        webRequest.ServicePoint.ConnectionLimit = 100;
        webRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36";
        webRequest.Proxy = null;
        WebResponse resp;
        string htmlCode = null;

        try
        {
           resp = webRequest.GetResponse();
           StreamReader sr = new StreamReader(resp.GetResponseStream(), System.Text.Encoding.UTF8);
           htmlCode = sr.ReadToEnd();
           sr.Close();
           resp.Close();
         }
    catch (Exception)

【问题讨论】:

  • 请格式化您的代码。
  • 有什么不规范的?
  • 您的代码在 IDE 中是这样的吗?
  • 是的,我是一个杂乱无章的人,我会努力为你美化它。你知道如何做我想要实现的超时吗?我不能只是中止线程。

标签: c# multithreading httpwebrequest


【解决方案1】:

明确地超时事件不是一个好方法。你可能想调查 Cancel Async Tasks after a Period of Time.

您可以在一段时间后取消异步操作 如果您不想,请使用 CancellationTokenSource.CancelAfter 方法 等待操作完成。该方法调度 取消任何未完成的相关任务 CancelAfter 表达式指定的时间段。

来自 MSDN 的示例代码:

// Declare a System.Threading.CancellationTokenSource.
        CancellationTokenSource cts;

        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            // Instantiate the CancellationTokenSource.
            cts = new CancellationTokenSource();    
            resultsTextBox.Clear();    
            try
            {
                // ***Set up the CancellationTokenSource to cancel after 2.5 seconds. (You 
                // can adjust the time.)
                cts.CancelAfter(2500);    
                await AccessTheWebAsync(cts.Token);
                resultsTextBox.Text += "\r\nDownloads succeeded.\r\n";
            }
            catch (OperationCanceledException)
            {
                resultsTextBox.Text += "\r\nDownloads canceled.\r\n";
            }
            catch (Exception)
            {
                resultsTextBox.Text += "\r\nDownloads failed.\r\n";
            }    
            cts = null; 
        }    

        // You can still include a Cancel button if you want to. 
        private void cancelButton_Click(object sender, RoutedEventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
            }
        }    

        async Task AccessTheWebAsync(CancellationToken ct)
        {
            // Declare an HttpClient object.
            HttpClient client = new HttpClient();    
            // Make a list of web addresses.
            List<string> urlList = SetUpURLList();    
            foreach (var url in urlList)
            {
                // GetAsync returns a Task<HttpResponseMessage>.  
                // Argument ct carries the message if the Cancel button is chosen.  
                // Note that the Cancel button cancels all remaining downloads.
                HttpResponseMessage response = await client.GetAsync(url, ct);    
                // Retrieve the website contents from the HttpResponseMessage. 
                byte[] urlContents = await response.Content.ReadAsByteArrayAsync();    
                resultsTextBox.Text +=
                    String.Format("\r\nLength of the downloaded string: {0}.\r\n"
                   , urlContents.Length);
            }
        }

还有Thread.Abort Method会终止线程。

编辑: 取消任务 - 更好的解释 (source)

Task 类提供了一种基于 CancellationTokenSource 类取消已启动任务的方法。

取消任务的步骤:

  1. 异步方法应该除了CancellationToken类型的参数

  2. 创建 CancellationTokenSource 类的实例,例如:var cts = new CancellationTokenSource();

  3. 将 CancellationToken 从实例传递到异步方法,例如:Task&lt;string&gt; t1 = GreetingAsync("Bulbul", cts.Token);

  4. 从长时间运行的方法中,我们必须调用 CancellationToken 的 ThrowIfCancellationRequested() 方法。

              static string Greeting(string name, CancellationToken token)
                {
                   Thread.Sleep(3000);
                   token. ThrowIfCancellationRequested();
                  return string.Format("Hello, {0}", name);
                }
    
  5. 在我们等待任务的地方找到OperationCanceledException

  6. 我们可以通过调用CancellationTokenSource实例的Cancel方法取消操作,OperationCanceledException会从长时间运行的操作中抛出。我们也可以设置时间取消对实例的操作。

更多详情 - MSDN Link

    static void Main(string[] args)
    {
        CallWithAsync();
        Console.ReadKey();           
    }

    async static void CallWithAsync()
    {
        try
        {
            CancellationTokenSource source = new CancellationTokenSource();
            source.CancelAfter(TimeSpan.FromSeconds(1));
            var t1 = await GreetingAsync("Bulbul", source.Token);
        }
        catch (OperationCanceledException ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    static Task<string> GreetingAsync(string name, CancellationToken token)
    {
        return Task.Run<string>(() =>
        {
            return Greeting(name, token);
        });
    }

    static string Greeting(string name, CancellationToken token)
    {
        Thread.Sleep(3000);
        token.ThrowIfCancellationRequested();
        return string.Format("Hello, {0}", name);
    }

【讨论】:

  • 但我可以简单地为我的 httpwebrequest 设置超时。有没有办法可以访问我正在创建的对象?我有一个所有线程的线程列表。
  • 您正在尝试Timeout HttpWebRequest 正在您的线程上执行。我不认为这是可能的,即使是这样。这不是正确的方法。
  • @tim_po - 请参阅编辑,我添加了CancellationToken的用法说明
猜你喜欢
  • 2010-11-27
  • 2010-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多