如何等待API响应从Pending状态变为完成状态?
问题
这个问题常被提及,但鲜少有人解答——就我所知,目前该场景下还没有相关答案,尽管我很希望被证明是错的,哪怕损失一些声望值;-)
我在C#中调用某个API后,返回的HttpResponseMessage对应的状态立刻是“Pending”:
JObject thing = JObject.Parse(await response.Content.ReadAsStringAsync()); thing["status"] // 值为 "Pending"
我原本想通过循环反复重试来获取更新后的状态,但“Pending”状态始终没有变化:
while (true) { JObject thing = JObject.Parse(await response.Content.ReadAsStringAsync()); Task.Delay(1000).Wait(); } thing["status"] // 仍然是 "Pending"
我甚至尝试在循环内重新调用该API端点:
while (true) { HttpResponseMessage response = await client.SendAsync(request); JObject thing = JObject.Parse(await response.Content.ReadAsStringAsync()); Task.Delay(1000).Wait(); }
但系统报错,提示无法重复使用同一个请求。请问有什么解决办法吗?
解决方案
- 不要重复读取同一响应内容:第一次调用
ReadAsStringAsync后,响应流已被读取完毕,后续再调用只会得到缓存的旧内容,状态自然不会更新。必须重新发起请求才能获取最新状态。 - 每次循环创建新的请求实例:
HttpRequestMessage是一次性对象,发送后无法复用。要在循环内部每次都生成新的请求对象,示例代码如下:
while (true) { // 每次循环创建新请求 var newRequest = new HttpRequestMessage(HttpMethod.Get, "你的API端点URL"); // 按需重新设置请求头、请求体等参数 // newRequest.Headers.Add("Authorization", "Bearer xxx"); // newRequest.Content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json"); HttpResponseMessage response = await client.SendAsync(newRequest); response.EnsureSuccessStatusCode(); // 可选:确保请求成功 JObject thing = JObject.Parse(await response.Content.ReadAsStringAsync()); if (thing["status"].ToString() != "Pending") { // 状态更新,退出循环 break; } // 用await替代Wait(),避免阻塞线程 await Task.Delay(1000); }
- 替换
Wait()为await:Task.Delay(1000).Wait()会阻塞当前线程,容易引发死锁或性能问题,异步代码里要始终用await等待延迟。 - 添加退出边界条件:无限循环风险高,建议设置最大重试次数或超时时间,防止程序无限等待:
int maxRetries = 30; int retryCount = 0; while (retryCount < maxRetries) { var newRequest = new HttpRequestMessage(HttpMethod.Get, "你的API端点URL"); HttpResponseMessage response = await client.SendAsync(newRequest); response.EnsureSuccessStatusCode(); JObject thing = JObject.Parse(await response.Content.ReadAsStringAsync()); if (thing["status"].ToString() != "Pending") { break; } retryCount++; await Task.Delay(1000); } if (retryCount >= maxRetries) { // 处理超时情况 Console.WriteLine("请求超时,状态未更新"); }
内容的提问来源于stack exchange,提问作者KWallace
相关产品推荐
相关产品推荐

