我的程序中有一个类调用API,每个请求都会通过以下函数在超时的情况下重试请求几次。
private readonly ISubjectService _subjectService;
public TeacherController(ISubjectService subjectService)
{
_subjectService= subjectService;
}
[HttpPost]
public IActionResult AddNewSubjects(IEnumerable<Subject> subjects)
{
var newSubjects= (from p in subjects
where p.State== Status.New
select p);
var result = _subjectService.SaveTeacherSubjects(newSubjects);
return View("ProfesorPages");
}
出于某种原因,虽然我得到一个protected async Task<HttpResponseMessage> RetryIfExceptionAsync(string urlString, HttpMethod httpMethod, HttpContent httpContent, byte exceptionRetries)
{
HttpResponseMessage httpResponse = null;
byte retries = exceptionRetries;
while (retries != 0)
{
var httpRequest = new HttpRequestMessage()
{
RequestUri = new Uri(urlString),
Method = httpMethod,
Content = httpContent
};
try
{
httpResponse = await Program.HttpClient.SendAsync(httpRequest); // <--- This is line 93
}
catch (TaskCanceledException taskCanceledException)
{
if (!taskCanceledException.CancellationToken.IsCancellationRequested)
{
Program.TimeoutDebugLog.Append(String.Format("{0} timeout, retries: {1}, url: {2}", httpMethod, retries, urlString)); //TimeoutDebugLog is a StringBuilder
await Task.Delay(200);
retries--;
continue;
}
}
break;
}
if (httpResponse == null)
{
using (var stream = new System.IO.FileStream("TimeoutDebugLog.txt", System.IO.FileMode.Append))
using (var writer = new System.IO.StreamWriter(stream))
{
writer.Write(Program.TimeoutDebugLog.ToString());
}
Program.TimeoutDebugLog.Clear();
throw new CustomHttpRequestException("Failed to obtain response after 5 attemps")
{
RequestUrl = urlString,
RequestMethod = httpMethod,
RequestContent = httpContent.ReadAsStringAsync().Result
};
}
else
{
return httpResponse;
}
}
说“不可能访问discarted object objectname:System.Net.Http.StringContent”。这是指向在第93行抛出异常的堆栈跟踪,我已在代码中指出:
ObjectDiposedException
我已经检查了the HttpClient source code at github,并且有一条评论说 at System.Net.Http.HttpContent.CheckDisposed()
at System.Net.Http.HttpContent.CopyToAsync(Stream stream, TransportContext context)
at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
--- end of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at AuditLogsDownload.ConsoleApp.Net.ApiCall.<RetryIfExceptionAsync>d__6.MoveNext() at {filepath}:line 93
用于处理请求的内容但不再是这种情况。我错过了什么?我该如何解决这个错误?事实上,每个类都是C#中的引用类型,这让我不确定如何继续。
答案 0 :(得分:0)
好的,我已经能够通过断开互联网(在SendAsync()
上抛出异常)并运行以下代码来复制问题:
class Program
{
static void Main(string[] args)
{
var client = new HttpClient();
var content = new StringContent("Hi");
while (true)
{
here:
var request = new HttpRequestMessage()
{
RequestUri = new Uri("https://httpbin.org/post"),
Method = HttpMethod.Post,
Content = content
};
try
{
var response = client.SendAsync(request).Result;
}
catch (Exception e)
{
goto here;
}
}
}
}
所以基本上HttpClient
源代码我看起来“曾经被放弃但不再有的请求”是.NET Core HttpClient
的源代码。在.NET框架中(这是我正在使用的)HttpClient
在SendAsync
抛出异常时仍然处理请求。
所以我想解决这个问题的方法是将字符串作为参数传递而不是StringContent
,然后在每StringContent
之前创建一个新的SendAsync()
。相当蹩脚但是我现在能想到的。