Task.Wait 始终 returns false 尽管任务已完成
Task.Wait always returns false although task finished
我正在使用 HttpClient
尝试在 Web API 控制器中执行 POST 方法。控制器方法是同步的。我是这样做的:
var response = owin.HttpClient.PostAsJsonAsync(uri, body);
之后我打电话给 Wait
:
var result = response.Wait(15000);
当 运行 这段代码时,我看到 http 完成执行,但 result
值始终为 false。我可以缺少什么?
编辑:
我现在尝试了一种异步方法,但它对我也没有帮助
public IHttpActionResult Add(Item item)
{
var result = _db.AddItem(item);
return Ok(result);
}
测试项目:
TestServer _owinTestServer;
public async Task<HttpResponse message> Method1(string url, object body)
{
return await
_owinTestServer.HttpClient.PostAsJsonAsync(url,body);
}
public async Task<ItemPreview> Method2(object body);
{
return await Method1("..", body ).Result.Content.ReadAsAsync<ItemPreview>();
}
[TestMethod]
public void test1()
{
Item item = new(...);
Method2(item).Continue with(task => {// Never reach here }
}
我做错了什么?
调试时我看到控制器方法 returns 一个很好的响应,但它永远不会回到我的测试
控制器方法是否同步并不重要。这纯粹是对服务器代码的关注。由于PostAsJsonAsync
方法是异步的,你需要await
它:
var response = await owin.HttpClient.PostAsJsonAsync(uri, body);
这将允许您的代码等待服务器的响应。
您正在混合异步和阻塞调用(即 .Result
、.Wait()
),这会导致死锁。
这看起来更像是测试客户端的阻塞问题。
在这种情况下,如果您想等待来自服务器的结果,则需要使测试始终异步。
将测试方法转换为异步
[TestMethod]
public async Task test1() {
//Arrange
Item item = new Item(...);
//Act
var preview = await Method2(item);
//Assert
Assert.IsNotNull(preview);
}
并更新方法以不混合异步和阻塞调用。
Method1
不需要 asyn/await
如果它在调用后不使用任务,那么它可以被删除,只需要方法 return 和 Task
可以期待
TestServer _owinTestServer;
public Task<HttpResponse> Method1(string url, object body) {
return _owinTestServer.HttpClient.PostAsJsonAsync(url, body);
}
Method2
需要 await
来自 Method1
的响应,然后获取其内容。
public async Task<ItemPreview> Method2(object body) {
var response = await Method1("..", body );
return await response.Content.ReadAsAsync<ItemPreview>();
}
我假设您的初始代码看起来像这样...
var response = owin.HttpClient.PostAsJsonAsync(uri, body);
var result = response.Wait(15000);
var itemPreview = response.Result.Content.ReadAsAsync<ItemPreview>();
...
是的,等待 15 秒后结果将为 false。这是因为您已经设置了请求,A.K.A 响应,但您实际上并没有进行调用,任何 response.Wait(n) 都将 return false。
您只需要启动 ReadAsAsync...
var response = owin.HttpClient.PostAsJsonAsync(uri, body);
var itemPreview = response.Result.Content.ReadAsAsync<ItemPreview>();
但是,我认为您会发现您可以一起跳过 response.Wait(n),因为它将 return 为真,因为 ReadAsAsync() 将等待 return 或失败。如果您要配置请求超时,您可以在 HttpClient 中执行此操作,并且您的 ReadAsAsync 将抛出 AggregateException 和 TaskCanceledException 的 InnerException。
附带说明一下,您不需要使用 owin.HttpClient 您只需实例化一个新的 HttpClient 即可。我相信您所指的 owin 对象是用于自托管您的 WebApi,我不知道这是否重要。但是假设您在 WebApi 上调用 Add(Item item) 并且 db.AddItem(item) 将 return 和 ItemPreview 对象,您的代码可能如下所示:
[TestMethod]
public void test1()
{
Item item = new(...);
var uri = "..";
var client = new HttpClient();
var response = client.PostAsJsonAsync(uri, item);
var itemPreview = response.Result.Content.ReadAsAsync<ItemPreview>();
/* The things to happen once you have item preview */
}
结果可能始终为假,因为 _db.AddItem 一直返回假。如果没有,我已经对您的代码进行了理想的更改,这应该适合您
TestServer _owinTestServer;
public async Task<HttpResponse message> Method1(string url, object body)
{
return await _owinTestServer.HttpClient.PostAsJsonAsync(url,body);
}
public async Task<ItemPreview> Method2(object body);
{
return await Method1("..", body ).Result.Content.ReadAsAsync<ItemPreview>();
}
[TestMethod]
public void test1()
{
Item item = new(...);
await Method2(item).ContinueWith(task => {// Never reach here }
}
由于方法 2 returns 是一个异步任务,ContinueWith 不会等待它完成,因此在方法调用时可能需要 await。
我正在使用 HttpClient
尝试在 Web API 控制器中执行 POST 方法。控制器方法是同步的。我是这样做的:
var response = owin.HttpClient.PostAsJsonAsync(uri, body);
之后我打电话给 Wait
:
var result = response.Wait(15000);
当 运行 这段代码时,我看到 http 完成执行,但 result
值始终为 false。我可以缺少什么?
编辑: 我现在尝试了一种异步方法,但它对我也没有帮助
public IHttpActionResult Add(Item item)
{
var result = _db.AddItem(item);
return Ok(result);
}
测试项目:
TestServer _owinTestServer;
public async Task<HttpResponse message> Method1(string url, object body)
{
return await
_owinTestServer.HttpClient.PostAsJsonAsync(url,body);
}
public async Task<ItemPreview> Method2(object body);
{
return await Method1("..", body ).Result.Content.ReadAsAsync<ItemPreview>();
}
[TestMethod]
public void test1()
{
Item item = new(...);
Method2(item).Continue with(task => {// Never reach here }
}
我做错了什么? 调试时我看到控制器方法 returns 一个很好的响应,但它永远不会回到我的测试
控制器方法是否同步并不重要。这纯粹是对服务器代码的关注。由于PostAsJsonAsync
方法是异步的,你需要await
它:
var response = await owin.HttpClient.PostAsJsonAsync(uri, body);
这将允许您的代码等待服务器的响应。
您正在混合异步和阻塞调用(即 .Result
、.Wait()
),这会导致死锁。
这看起来更像是测试客户端的阻塞问题。
在这种情况下,如果您想等待来自服务器的结果,则需要使测试始终异步。
将测试方法转换为异步
[TestMethod]
public async Task test1() {
//Arrange
Item item = new Item(...);
//Act
var preview = await Method2(item);
//Assert
Assert.IsNotNull(preview);
}
并更新方法以不混合异步和阻塞调用。
Method1
不需要 asyn/await
如果它在调用后不使用任务,那么它可以被删除,只需要方法 return 和 Task
可以期待
TestServer _owinTestServer;
public Task<HttpResponse> Method1(string url, object body) {
return _owinTestServer.HttpClient.PostAsJsonAsync(url, body);
}
Method2
需要 await
来自 Method1
的响应,然后获取其内容。
public async Task<ItemPreview> Method2(object body) {
var response = await Method1("..", body );
return await response.Content.ReadAsAsync<ItemPreview>();
}
我假设您的初始代码看起来像这样...
var response = owin.HttpClient.PostAsJsonAsync(uri, body);
var result = response.Wait(15000);
var itemPreview = response.Result.Content.ReadAsAsync<ItemPreview>();
...
是的,等待 15 秒后结果将为 false。这是因为您已经设置了请求,A.K.A 响应,但您实际上并没有进行调用,任何 response.Wait(n) 都将 return false。
您只需要启动 ReadAsAsync...
var response = owin.HttpClient.PostAsJsonAsync(uri, body);
var itemPreview = response.Result.Content.ReadAsAsync<ItemPreview>();
但是,我认为您会发现您可以一起跳过 response.Wait(n),因为它将 return 为真,因为 ReadAsAsync() 将等待 return 或失败。如果您要配置请求超时,您可以在 HttpClient 中执行此操作,并且您的 ReadAsAsync 将抛出 AggregateException 和 TaskCanceledException 的 InnerException。
附带说明一下,您不需要使用 owin.HttpClient 您只需实例化一个新的 HttpClient 即可。我相信您所指的 owin 对象是用于自托管您的 WebApi,我不知道这是否重要。但是假设您在 WebApi 上调用 Add(Item item) 并且 db.AddItem(item) 将 return 和 ItemPreview 对象,您的代码可能如下所示:
[TestMethod]
public void test1()
{
Item item = new(...);
var uri = "..";
var client = new HttpClient();
var response = client.PostAsJsonAsync(uri, item);
var itemPreview = response.Result.Content.ReadAsAsync<ItemPreview>();
/* The things to happen once you have item preview */
}
结果可能始终为假,因为 _db.AddItem 一直返回假。如果没有,我已经对您的代码进行了理想的更改,这应该适合您
TestServer _owinTestServer;
public async Task<HttpResponse message> Method1(string url, object body)
{
return await _owinTestServer.HttpClient.PostAsJsonAsync(url,body);
}
public async Task<ItemPreview> Method2(object body);
{
return await Method1("..", body ).Result.Content.ReadAsAsync<ItemPreview>();
}
[TestMethod]
public void test1()
{
Item item = new(...);
await Method2(item).ContinueWith(task => {// Never reach here }
}
由于方法 2 returns 是一个异步任务,ContinueWith 不会等待它完成,因此在方法调用时可能需要 await。