我有一个在与各种网站通信的服务器上运行的程序。其中一个网站很快就要求通过http POST请求进行通信,因此需要新版本的程序。有时,程序需要同时发出几百个POST请求,因此异步发出请求对性能很重要。我现在尝试了两种编码方式,两种方式通过抛出AccessViolationException以完全相同的方式间歇性地失败。即使程序完全由托管代码组成,也会发生这种情况,因此AccessViolationExceptions应该是不可能的(请参阅Microsoft对AccessViolationException Class的评论)。
我在两周前发布了一个关于我的第一种编码方法的问题(参见System.AccessViolationException at ...)。从那以后我发现了System.Net.Http.HttpClient
类,我的第二种编码方法尝试使用它,因此它与第一种方法完全不同。修改后的代码的核心如下:
HttpClient httpclient = new HttpClient();
// set up httpclient with headers etc
System.Threading.CancellationTokenSource cts = new System.Threading.CancellationTokenSource();
using (StringContent sc = new StringContent(stringContent)) {
sc.Headers.ContentType = new MediaTypeWithQualityHeaderValue(ContentType);
using (Task<HttpResponseMessage> task_postasync = httpclient.PostAsync(EndPoint, sc, cts.Token)) {
task_postasync.Wait();
if (!task_postasync.IsCompleted) {
// cater for failure
}
using (HttpResponseMessage response = task_postasync.Result) {
using (Task<string> task_ReadAsStringAsync = response.Content.ReadAsStringAsync()) {
task_ReadAsStringAsync.Wait();
if (!task_ReadAsStringAsync.IsCompleted) {
// cater for failure
}
string str = task_ReadAsStringAsync.Result;
// str is the now the result of the http POST request :-)
}
}
}
}
修订版和原始代码都在大部分时间内工作,但偶尔它们都会因抛出AccessViolationException
而失败。此外,对于两个代码版本,异常的位置都指定为System.Threading._IOCompletionCallback.PerformIOCompletionCallback()
。这告诉我,两个版本都因为在.Net库中遇到同样的低级错误而失败。无论我是将代码运行为32位还是64位,都会出现问题。
在服务器上,ThreadPool中的最小完成端口数默认为24,最大数量默认为1000.大多数时候我一直将最小数设置为最大数1000,但我仍然得到{{ 1}}当我将所有内容保留为默认值时。
我尝试通过运行非托管代码调试来查看汇编程序中抛出异常的位置。当以下代码中的指令指针AccessViolationException
为EIP
时抛出异常:
7606336A
在行76063354 nop
76063355 nop
76063356 nop
76063357 nop
76063358 mov edi,edi
7606335A push ebp
7606335B mov ebp,esp
7606335D test ecx,ecx
7606335F jne 760661DA
76063365 push dword ptr [ebp+8]
76063368 call edx
7606336A push eax
7606336B call dword ptr ds:[76060704h]
76063371 nop
76063372 nop
76063373 nop
76063374 nop
76063375 nop
76063376 mov edi,edi
76063378 push ebp
76063379 mov ebp,esp
7606337B sub esp,62Ch
76063381 mov eax,dword ptr ds:[761303ACh]
76063386 xor eax,ebp
76063388 mov dword ptr [ebp-4],eax
7606338B cmp dword ptr [ebp+8],1
7606338F push esi
76063390 mov esi,dword ptr [ebp+0Ch]
76063393 je 76066AF1
76063399 cmp dword ptr [ebp+8],2
7606339D jne 760633A8
7606339F cmp byte ptr ds:[76130002h],0
之后立即抛出异常并且寄存器call edx
为零,所以这看起来好像它试图调用内存地址为零并且失败的东西。
为了帮助优化大量的同时Web请求,程序有一个配置文件,如下所示:
edx
这些设置已经很长时间了,并且过去在通过互联网获得高性能以获得高性能时非常有用。
我原本以为制作异步http POST请求应该很容易,但我似乎无法避免间歇<?xml version="1.0"?>
<configuration>
<system.net>
<connectionManagement>
<add address="*" maxconnection="5000"/>
</connectionManagement>
<settings>
<servicePointManager expect100Continue="false" useNagleAlgorithm="false"/>
</settings>
</system.net>
<runtime>
<legacyCorruptedStateExceptionsPolicy enabled="true" />
</runtime>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
。有人可以帮忙吗?
答案 0 :(得分:1)
我做了类似你所描述的事情。我将http请求包装在BackgroundWorker中。你可以解雇很多很多这样的事情并为自己省去所有异步疯狂的工作。
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.110).aspx