none
关于HttpWebRequest多线程引发的0xc0000005错误 RRS feed

  • 问题

  • 用HttpWebRequest与HttpWebResponse写的多线程爬虫,通过HttpWebRequest.GetResponse()方法获取HttpWebResponse实例时偶发不可捕捉到的0xc0000005错误,找不到原因,求助各位了。

    已经设定了HTTP并发数为512,多线程(目前最高并发60多个线程)执行下方的代码,省略了部分内容,期间主程序还会以并发WebClient.OpenRead的方式对代理服务器地址进行可用性测试(最大并发量100)。

    Dim request As HttpWebRequest = WebRequest.Create(URL)
    ’此处省略了对request对象的属性设定代码,其中有的线程有设定代理情况
    Dim response As HttpWebResponse
    Try
        response = CType(request.GetResponse(), HttpWebResponse)   '此步偶发错误
    Catch ex As Exception
    
    End Try

    以上代码正常情况下遇到网页无法访问等常规错误时可以捕获并处置,但是在调试时偶然(无规律,有时调试2、3小时抛出,有时十多个小时甚至24小时以上)会抛出以下错误信息:

    发生了 托管调试助手 "FatalExecutionEngineError"
      Message=托管调试助手 "FatalExecutionEngineError":“运行时遇到了错误。此错误的地址为 0xfe5c68b0,在线程 0xffc8 上。错误代码为 0xc0000005。此错误可能是 CLR 中的 bug,或者是用户代码的不安全部分或不可验证部分中的 bug。此 bug 的常见来源包括用户对 COM-interop 或 PInvoke 的封送处理错误,这些错误可能会损坏堆栈。”

    在程序部署后运行出错时,系统日志会连续记录以下2个错误并关闭程序:

    应用程序:*********.exe
    Framework 版本: v4.0.30319
    说明: 由于 .NET 运行时中出现内部错误,进程终止 位于 IP 00007FFA8FCBF360 (00007FFA8FB40000),退出代码为 80131506。
    错误应用程序名称: *******.exe,版本: 2.1.0.0,时间戳: 0x5a0537cc

    错误模块名称: clr.dll,版本: 4.7.2110.0,时间戳: 0x597bd642
    异常代码: 0xc0000005
    错误偏移量: 0x000000000017f360
    错误进程 ID: 0xa6b4

    相关问题,请大家帮忙解决:

    1、调试时发现多线程执行上方代码获取网页数据时系统经常在进行GC垃圾收回,该错误的出现是否为访问了已被回收的response对象

    2、是否与突发的HTTP并发访问有关,加上代理测试机制,程序有时候并发HTTP数量会接近200。

    3、0xc0000005错误和访问非法资源有关?是否有可能是程序运行用户权限问题导致的文件写入异常引发?比如系统日志的写入错误

    4、在同一台服务器以window server2008R2和window server2016测试均出现问题,但相同的程序在部署在一个云主机,并发数很小的情况下很稳定。

    感谢大家,为我解惑。虽然程序在出错后有恢复机制,但最求完美,希望爬虫稳定不掉……



    • 已编辑 shusir 2017年11月15日 4:15
    2017年11月15日 3:15

全部回复

  • Hi,

    感谢在MSDN论坛发帖。

    从这个错误信息来看访问非法的内存出错了,我觉的可能是访问非法的response 出现了错误。

    如果response 已经被销毁了,你的代码还有可能会访问吗?

    据我所知,.NET Framework 中的GC在处理的时候,会挂起其他线程,这样其他线程就不会有机会再去访问释放的资源,但是GC执行完以后,如果访问释放的response, 就会出错。

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年11月15日 7:09
    版主
  • 我测试过在执行response = CType(request.GetResponse(), HttpWebResponse)前将response对象=nothing释放,这种情况下可以捕捉到错误,并继续程序。GC释放资源的机制应该不是=nothing的原理吧。如果真是GC释放了request对象引发的此错误,我该如何避免这个问题?VB.NET没有C#fixed语句(我猜fixed可以解决)。或者控制并合理分配一下并发线程?
    2017年11月15日 7:24
  • Hi,

    你可以自己手动释放这些资源,这样错误,就会有人控制,当response 用完以后,自己释放。

    GC的工作原理大概如下,他会把资源标志成 0 1 2 代,通过这些标志来释放资源。所以就有可能释放之前不用的资源,但是在你释放后,又需要用。

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年11月15日 7:59
    版主
  • 我刚才一直理解是request被GC释放掉,现在仔细看你的解释才发现是response在使用前被GC释放掉。那么我还是那个问题,我要如何控制response不在new后就被释放?
    2017年11月15日 8:26
  • Hi,

    我查找了很多资料,没有发现有什么办法让GC不主动释放managed 资源, 如果要让GC不主动释放unmanaged 资源,一般我们使用unsafe 这个关键字,就可以了,这样GC就不会释放里面的资源了。

    我觉得你在使用response 的时候,可以去判断一下,是不是null,以免出现访问出错。

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年11月16日 7:54
    版主