我有一个asp.net Web API。 (净框架4.6.1)我正在其中一项操作中调用第三方rest API(产品)。在功能测试中,一切正常,没有问题。但是,当我执行尖峰测试(假设有100位用户,10秒的启动时间)时,经过一些成功的响应,我得到了System.Threading.Tasks.TaskCanceledException: A task was canceled error
。我用谷歌搜索发现可能是由于超时。我添加了TimeSpan.FromSeconds(600);
,但仍然遇到相同的错误。
这就是我所谓的第三方API的方式。异步调用有什么问题吗?您能看看我的代码吗?
public class UtilitiesTest
{
private static readonly HttpClient _httpClient = new HttpClient();
//some not relevant code here
public static async Task<HttpResponseMessage> CallRazer(GameRequest gameRequest, string url)
{
try
{
FormUrlEncodedContent content = null;
if (url == "Product/")
{
try
{
//some code here
//Timeout
_httpClient.Timeout = TimeSpan.FromSeconds(600);
//Call Game
var response = await _httpClient.PostAsync("https://test.com/" + url, content);
return response;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
finally
{
content.Dispose();
}
}
else
{
try
{
//some code here
//Call Game
var response = await _httpClient.PostAsync("https://test.com/" + url, content);
return response;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
finally
{
content.Dispose();
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
这就是我所说的Razer:
private async Task<HttpResponseMessage> CallProducts()
{
//some code here
#region Call Razer for products
//**Call Razer**
var response = await Utilities.CallRazer(products, "Product/");
var htmlResponse = await response.Content.ReadAsStringAsync();
var model = JsonConvert.DeserializeObject<ProductResponseDto>(htmlResponse);
// some code here
return response;
}
另一个论坛的某人建议我使用HTTPWeb Request而不是Httpclient。所以我像下面那样更改了代码,所有麻烦都消失了。
//HTTPWebRequest
var request = (HttpWebRequest) WebRequest.Create("http://test.com" + url);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
var keyValueContent = productRequest.ToKeyValue();
var formUrlEncodedContent = new FormUrlEncodedContent(keyValueContent);
var urlEncodedString = await formUrlEncodedContent.ReadAsStringAsync();
using (var streamWriter = new StreamWriter(await request.GetRequestStreamAsync()))
{
streamWriter.Write(urlEncodedString);
}
HttpWebResponse httpResponse = (HttpWebResponse) (await request.GetResponseAsync());
response = new HttpResponseMessage
{
StatusCode = httpResponse.StatusCode,
Content = new StreamContent(httpResponse.GetResponseStream()),
};
return response;
答案 0 :(得分:0)
如果600秒后仍然超时,则您的Web服务就跟不上。
但是,是的,超时将生成TaskCanceledException
,这一点都不直观。实际上,这至少会在.NET Core(just fixed last week)中改变,但这对您没有帮助。
这是我用来重新抛出TimeoutException
的代码。可能引发TaskCanceledException
的唯一 other 原因是,如果您通过了CancellationToken
并最终被取消,但您没有这样做。所以绝对是超时。
} catch (TaskCanceledException) {
//Could have been caused by cancellation or timeout if you used one.
//If that was the case, rethrow.
//cancellationToken.ThrowIfCancellationRequested();
//HttpClient throws TaskCanceledException when the request times out. That's dumb.
//Throw TimeoutException instead and say how long we waited.
string time;
if (_httpClient.Timeout.TotalHours > 1) {
time = $"{_httpClient.Timeout.TotalHours:N1} hours";
} else if (_httpClient.Timeout.TotalMinutes > 1) {
time = $"{_httpClient.Timeout.TotalMinutes:N1} minutes";
} else if (_httpClient.Timeout.TotalSeconds > 1) {
time = $"{_httpClient.Timeout.TotalSeconds:N1} seconds";
} else {
time = $"{_httpClient.Timeout.TotalMilliseconds:N0} milliseconds";
}
throw new TimeoutException($"No response after waiting {time}.");
}