【发布时间】:2017-12-26 03:20:28
【问题描述】:
我正在使用 .NET Framework 4.6.1。
我的 web api 中有一个控制器,其中有静态 HttpClient 来处理所有 http 请求。在 IIS 上托管我的应用程序后,大约每月一次,对于我的应用程序的所有传入请求,我都会收到以下异常:
System.ArgumentNullException: Value cannot be null.
at System.Threading.Monitor.Enter(Object obj)
at System.Net.Http.Headers.HttpHeaders.ParseRawHeaderValues(String name, HeaderStoreItemInfo info, Boolean removeEmptyHeader)
at System.Net.Http.Headers.HttpHeaders.AddHeaders(HttpHeaders sourceHeaders)
at System.Net.Http.Headers.HttpRequestHeaders.AddHeaders(HttpHeaders sourceHeaders)
at System.Net.Http.HttpClient.PrepareRequestMessage(HttpRequestMessage request)
at System.Net.Http.HttpClient.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.PutAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken)
at Attributes.Controllers.AttributesBaseController.<UpdateAttributes>d__6.MoveNext() in D:\Git\PortalSystem\Attributes\Controllers\AttributesBaseController.cs:line 42
如果我在 IIS 上重新启动应用程序池,一切都会重新开始正常工作。这是我的代码:
public class AttributesBaseController : ApiController
{
[Inject]
public IPortalsRepository PortalsRepository { get; set; }
private static HttpClient Client = new HttpClient(new HttpClientHandler { Proxy = null, UseProxy = false })
{ Timeout = TimeSpan.FromSeconds(double.Parse(WebConfigurationManager.AppSettings["httpTimeout"])) };
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
protected async Task UpdateAttributes(int clientId, int? updateAttrId = null)
{
try
{
Client.DefaultRequestHeaders.Accept.Clear();
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
#region Update Client Dossier !!! BELOW IS LINE 42 !!!!
using (var response = await Client.PutAsync(new Uri(WebConfigurationManager.AppSettings["dossier"] + "api/dossier?clientId=" + clientId), null))
{
if (!response.IsSuccessStatusCode)
{
logger.Error($"Dossier update failed");
}
}
#endregion
#region Gather Initial Info
var checkSystems = PortalsRepository.GetCheckSystems(clientId);
var currentAttributes = PortalsRepository.GetCurrentAttributes(clientId, checkSystems);
#endregion
List<Task> tasks = new List<Task>();
#region Initialize Tasks
foreach (var cs in checkSystems)
{
if (!string.IsNullOrEmpty(cs.KeyValue))
{
tasks.Add(Task.Run(async () =>
{
var passedAttributes = currentAttributes.Where(ca => ca.SystemId == cs.SystemId && ca.AttributeId == cs.AttributeId &&
(ca.SysClientId == cs.KeyValue || ca.OwnerSysClientId == cs.KeyValue)).ToList();
if (cs.AttributeId == 2 && (updateAttrId == null || updateAttrId == 2))
{
await UpdateOpenWayIndividualCardsInfo(passedAttributes, cs, clientId);
}
else if (cs.AttributeId == 3 && (updateAttrId == null || updateAttrId == 3))
{
await UpdateEquationAccountsInfo(passedAttributes, cs, clientId);
}
else if (cs.AttributeId == 8 && (updateAttrId == null || updateAttrId == 8))
{
await UpdateOpenWayCorporateInfo(passedAttributes, cs, clientId);
}
else if (cs.AttributeId == 9 && (updateAttrId == null || updateAttrId == 9))
{
await UpdateEquationDealsInfo(passedAttributes, cs, clientId);
}
else if (cs.AttributeId == 10 && (updateAttrId == null || updateAttrId == 10))
{
await UpdateOpenWayIndividualCardDepositsInfo(passedAttributes, cs, clientId);
}
else if (cs.AttributeId == 16 && (updateAttrId == null || updateAttrId == 16))
{
await UpdateOpenWayBonusInfo(passedAttributes, cs, clientId);
}
else if (cs.AttributeId == 17 && (/*updateAttrId == null ||*/ updateAttrId == 17))
{
await UpdateExternalCardsInfo(passedAttributes, cs, clientId);
}
if (cs.AttributeId == 18 && (updateAttrId == null || updateAttrId == 18))
{
await UpdateCRSInfo(passedAttributes, cs, clientId);
}
else if (cs.AttributeId == 22 && (updateAttrId == null || updateAttrId == 22))
{
await UpdateCardInsuranceInfo(passedAttributes, cs, clientId);
}
}));
}
}
#endregion
// Run all tasks
await Task.WhenAny(Task.WhenAll(tasks.ToArray()), Task.Delay(TimeSpan.FromSeconds(double.Parse(WebConfigurationManager.AppSettings["taskWaitTime"]))));
}
catch (Exception ex)
{
logger.Error(ex);
}
}
}
谁能给我建议/帮助来解决问题?我只是不知道问题是出在我使用 HttpClient 处理任务的方式上,还是在 IIS 上发生了一些不好的事情。
【问题讨论】:
-
"...或者 IIS 上发生了一些不好的事情" -- 并非完全不可能,但极不太可能。但是,如果没有一个好的minimal reproducible example 可以可靠地重现问题,Stack Overflow 社区就无法提供任何好的、具体的答案。
-
@PeterDuniho 问题是如果我手动执行请求,我将无法重现该问题。也许你可以给我一些建议,从哪里开始调查这个问题?
-
第一步与任何其他问题相同:尽可能简化场景。既然你说它每月只发生一次,那么走这条路可能需要一段时间。另一种标准技术是添加日志记录;在这种情况下,这可能是您最好的选择。假设您至少对导致问题的一般代码区域有所了解,请添加日志记录以记录所有状态,以便您了解重现问题所需的状态。 ...
-
... 最初这可能只是变量和类成员,但您可能还想记录客户端数量、身份、线程池状态等内容。
-
@PeterDuniho 另外,我忘了提到我为应用程序池提供了 3 个工作进程。当这个异常发生时,所有的工作进程不会一下子失败,它们会一个一个地失败。
标签: c# .net iis async-await