【问题标题】:Webrequest sudenly stops workingWebrequest 突然停止工作
【发布时间】:2010-02-18 22:21:03
【问题描述】:
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(baseurl + url);
req.Timeout = 1000 * 10;
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
Stream str = response.GetResponseStream();
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.Load(str);
response.Close();
string imgurl = doc.DocumentNode.SelectSingleNode("//div[@class='one-page']/a/img[@class='manga-page']").Attributes["src"].Value;
req = (HttpWebRequest)HttpWebRequest.Create(imgurl);
req.Timeout = 1000 * 10;
response = (HttpWebResponse)req.GetResponse();
str = response.GetResponseStream();
Image img = Image.FromStream(str);
response.Close();
return img;

我在循环中运行此代码(使用多个线程)以下载大约 4000 张图像,它在前数百张图片中运行良好,但随后(在每次我尝试的不同时间点)它突然停止工作,并且每次调用“req.GetResponse()”都会导致 TimeoutException。我不知道为什么会发生这种情况,也不知道可能出了什么问题或如何处理它。任何帮助将不胜感激。

我用来运行这个函数的代码(它叫做GetPage(int),叫做c.GetPage(t))如下:

for (int j = 0; j < 2; j++)
{
    BackgroundWorker bw = new BackgroundWorker();
    num[bw] = j;
    bgs.Add(bw);
    bw.DoWork += (object sender, DoWorkEventArgs doargs) =>
    {
        int t = -1;
        lock (lockObjForQueueOperations)
        {
            if (images.Count != 0)
                t = images.Dequeue();
        }
        if(t < 0)
        {
            doargs.Result = false;
            return;
        }
        currently[sender] = t;
        Image img;
        try { img = c.GetPage(t); }
        catch (Exception e)
        {
            lock (lockObjForQueueOperations)
            {
                images.Enqueue(t);
            }
            lock (Console.Title)
            {
                if (num[sender] == 0) Console.ForegroundColor = ConsoleColor.Cyan;
                else if (num[sender] == 1) Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("**ERR: Error fetshing page {0}, errormsg: {1}", t, e.Message);
                Console.ForegroundColor = ConsoleColor.White;
            }
            doargs.Result = true;
            Thread.Sleep(1000*2);
            return;
        }
        lock (Console.Title)
        {
            if (num[sender] == 0) Console.ForegroundColor = ConsoleColor.Cyan;
            else if (num[sender] == 1) Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("\t\tLoaded page {0} of {1}.", t + 1, c.PagesCount);
            Console.ForegroundColor = ConsoleColor.White;
        }
        string imgpath = Path.Combine(ndir, "Page " + (t + 1) + ".png");
        img.Save(imgpath, System.Drawing.Imaging.ImageFormat.Png);
        img.Dispose();
        doargs.Result = true;
    };
    bw.RunWorkerCompleted += (object sender, RunWorkerCompletedEventArgs runargs) =>
    {
        if ((bool)runargs.Result) bw.RunWorkerAsync();
        else
        {
            finnishedworkers++;
            if (finnishedworkers == 2) restetter.Set();
            bw.Dispose();
        }
    };
    bw.RunWorkerAsync();
}

【问题讨论】:

  • 这可能是由您的 ISP 或网站主机中的 DDOS 保护引起的。
  • 嗯,我一开始也是这么想的,但后来我尝试进入我的程序试图从我的浏览器进入的同一页面,它工作了,但我的程序仍然超时。
  • @Alxandr,我面临同样的问题。你找到解决这个问题的办法了吗?

标签: c# multithreading webrequest


【解决方案1】:

HttpWebRequest 中的 Timeout 属性以毫秒为单位。目前将其设置为 10,000 只需 10 秒,根据带宽和要提取的数据的大小以及正在运行的代码的复杂性,这可能还不够。我说先尝试增加它。

【讨论】:

  • 资源在一秒内加载完毕。我设置了超时,因为我厌倦了等待超时异常。
  • 我也尝试在不设置超时的情况下运行代码,但是给我异常花了太长时间(我只是在等待异常,什么都没有发生......)。跨度>
【解决方案2】:

你的设计很糟糕。不要为每个请求创建线程,而是尝试调用 BeginGetResponse。该框架将处理从线程池分配线程以服务您的请求。

添加对 ServicePointManager.SetDefaultConnectionLimit (?) 不确定的调用到 100 之类的数字。

创建一个计数与连接限制计数匹配的信号量。

在调用 BeginGetResponse 的函数中,在调用之前添加对 semaphore.WaitOne() 的调用 get BeginGet...

在您的 EndGetResponse() 处理程序中,调用 semaphore.Release() 以允许下一个请求继续。

您可能正在用自己的所有线程耗尽线程池。监控你的进程,看看你是否不能执行并且总共只使用 5-10 个线程。也许您可以记录 Thread.Current.ThreadID 以查看 SAME 线程如何处理多个请求。

完成了数十亿次。真的。

【讨论】:

  • 我不认为我在只运行 3 个线程的情况下耗尽了线程池?还是每次调用“RunWorkerAsync”时后台工作者都会创建一个新线程?
猜你喜欢
  • 2017-08-22
  • 2021-02-01
  • 2016-12-29
  • 2018-05-09
  • 2015-12-07
  • 2015-08-23
  • 2014-02-05
  • 2013-09-06
相关资源
最近更新 更多