如果 API 关闭,如何使 PostAsync 响应
How to make PostAsync respond if API is down
我正在使用这些命令调用 API:
byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(message);
var content = new ByteArrayContent(messageBytes);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
HttpResponseMessage response = client.PostAsync(ApiUrl, content).Result;
但是代码在 PostAsync 行停止执行。我在下一行放置了一个断点,但它从未到达。它不会立即抛出错误,但几分钟后会抛出如下错误:
System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
我认为这意味着 API 已关闭。我该怎么做才能让 PostAsync
立即返回错误,即使 API 已关闭,以便我可以处理错误并通知用户?
谢谢。
从广义上讲,您要问的是 "How can I check if an API is available?",对此的答案取决于您希望获得多低的级别,以及您希望针对每个不可用级别执行的操作:
- 是否有互联网连接?是否值得首先在本地进行探测(因为检查速度相对较快)?
- 服务器地址是否正确?如果错了,等多久都没关系。用户可以配置吗?
- 地址是否正确但服务器无法或不愿响应?然后怎样呢?
如果您愿意将它们全部集中到一个 "can't contact server in a reasonable amount of time" 桶中,有几种方法:
减少超时(注意)
在你给出的情况下,听起来你的请求只是超时:地址或端口错误,服务器负载过大,无法及时响应,你正在尝试联系使用 SSL 的非 SSL 端点,反之亦然。在任何这些情况下,您无法知道 请求是否超时,直到它实际超时超时。您可以做的一件事是减少 HttpClient request timeout。当心:太低会导致用户连接缓慢超时,这是一个比您遇到的问题更严重的问题。
预检
您可以在每次调用之前、定期或在客户端初始化早期的某个时间点快速探测 API 以查看它是否有响应。这可以在构建 UI 时拆分为异步任务或后台任务等。这使您有更多时间等待响应,并且如果 API 正在响应,则作为额外奖励慢慢地,您可以将此通知您的用户,以便他们知道不要期望对他们的点击立即做出反应。这将改善用户体验。如果预检查失败,您可以显示错误并建议用户检查连接、检查服务器地址(如果它是可配置的)、重试等。
使用 CancellationToken
您可以通过 CancellationToken into PostAsync with a suitable timeout set, which also allows you to let the user cancel the request if they want to. Read up on CancellationToken 获取更多信息。
编辑:正如 Alex 所指出的,这一行通常不是您处理异步任务的方式:
HttpResponseMessage response = client.PostAsync(ApiUrl, content).Result;
改为:
HttpResponseMessage response = await client.PostAsync(ApiUrl, content);
当然调用方法也需要被标记为异步,等等 ("It's asyncs, "),但这是一件好事 - 这意味着您的代码在等待服务器响应时不会阻塞线程。
阅读 here 以获得一些好处 material。
希望对您有所帮助
我正在使用这些命令调用 API:
byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(message);
var content = new ByteArrayContent(messageBytes);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
HttpResponseMessage response = client.PostAsync(ApiUrl, content).Result;
但是代码在 PostAsync 行停止执行。我在下一行放置了一个断点,但它从未到达。它不会立即抛出错误,但几分钟后会抛出如下错误:
System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
我认为这意味着 API 已关闭。我该怎么做才能让 PostAsync
立即返回错误,即使 API 已关闭,以便我可以处理错误并通知用户?
谢谢。
从广义上讲,您要问的是 "How can I check if an API is available?",对此的答案取决于您希望获得多低的级别,以及您希望针对每个不可用级别执行的操作:
- 是否有互联网连接?是否值得首先在本地进行探测(因为检查速度相对较快)?
- 服务器地址是否正确?如果错了,等多久都没关系。用户可以配置吗?
- 地址是否正确但服务器无法或不愿响应?然后怎样呢?
如果您愿意将它们全部集中到一个 "can't contact server in a reasonable amount of time" 桶中,有几种方法:
减少超时(注意)
在你给出的情况下,听起来你的请求只是超时:地址或端口错误,服务器负载过大,无法及时响应,你正在尝试联系使用 SSL 的非 SSL 端点,反之亦然。在任何这些情况下,您无法知道 请求是否超时,直到它实际超时超时。您可以做的一件事是减少 HttpClient request timeout。当心:太低会导致用户连接缓慢超时,这是一个比您遇到的问题更严重的问题。
预检
您可以在每次调用之前、定期或在客户端初始化早期的某个时间点快速探测 API 以查看它是否有响应。这可以在构建 UI 时拆分为异步任务或后台任务等。这使您有更多时间等待响应,并且如果 API 正在响应,则作为额外奖励慢慢地,您可以将此通知您的用户,以便他们知道不要期望对他们的点击立即做出反应。这将改善用户体验。如果预检查失败,您可以显示错误并建议用户检查连接、检查服务器地址(如果它是可配置的)、重试等。
使用 CancellationToken
您可以通过 CancellationToken into PostAsync with a suitable timeout set, which also allows you to let the user cancel the request if they want to. Read up on CancellationToken 获取更多信息。
编辑:正如 Alex 所指出的,这一行通常不是您处理异步任务的方式:
HttpResponseMessage response = client.PostAsync(ApiUrl, content).Result;
改为:
HttpResponseMessage response = await client.PostAsync(ApiUrl, content);
当然调用方法也需要被标记为异步,等等 ("It's asyncs,
希望对您有所帮助