大佬教程收集整理的这篇文章主要介绍了使用await / async时,HttpClient.GetAsync(...)从不返回,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
您正在滥用API。
情况就是这样:在ASP.NET中,一次只有一个线程可以处理一个请求。如果有必要,您可以执行一些并行处理(从线程池中借用其他线程),但是只有一个线程具有请求上下文(其他线程没有请求上下文)。
这由ASP.NET管理SynchronizationContext
。
默认情况下,当您使用await
a时Task
,该方法将在捕获到的对象SynchronizationContext
(或没有捕获TaskScheduler
到的对象SynchronizationContext
)上继续。通常,这就是您想要的:异步控制器操作将执行await
某些操作,并且在恢复操作时,将在请求上下文中恢复操作。
因此,这就是test5
失败的原因:
Test5Controller.Get
执行AsyncAwait_GetSomeDataAsync
(在ASP.NET请求上下文中)。AsyncAwait_GetSomeDataAsync
执行httpClIEnt.GetAsync
(在ASP.NET请求上下文中)。httpClIEnt.GetAsync
返回一个uncompleted Task
。AsyncAwait_GetSomeDataAsync
等待Task
; 由于未完成,因此AsyncAwait_GetSomeDataAsync
返回uncompleted Task
。Test5Controller.Get
当前线程,直到Task
完成为止。Task
并由返回httpClIEnt.GetAsync
完成。AsyncAwait_GetSomeDataAsync
尝试在ASP.NET请求上下文中恢复。但是,在该上下文中已经有一个线程:该线程在中被阻塞Test5Controller.Get
。这就是其他方法起作用的原因:
test1
,test2
和test3
):在ASP.NET请求上下文 之外 ,Continuations_GetSomeDataAsync
调度到线程池的继续。这使得返回者可以完成而不必重新输入请求上下文。 __Task``Continuations_GetSomeDataAsync
test4
和test6
):由于Task
正在 等待 ,因此不会阻止ASP.NET请求线程。AsyncAwait_GetSomeDataAsync
当准备好继续时,这允许使用ASP.NET请求上下文。这是最佳做法:
async
方法中,请ConfigureAwait(false)
尽可能使用。在你的情况,这将改变AsyncAwait_GetSomeDataAsync
是var result = await httpClIEnt.GetAsync("http://stackoverflow.com", httpCompletionoption.ResponseheadersRead).ConfigureAwait(false);
Task
s;它是async
一路下滑。换句话说,请使用await
代替GetResult
(Task.Result
并且Task.Wait
也应替换为await
)。这样,您将获得两个好处:延续(AsyncAwait_GetSomeDataAsync
方法的其余部分)在基本线程池线程上运行,该线程不必输入ASP.NET请求上下文;控制器本身是async
(不会阻塞请求线程)。
更多信息:
async
/ await
介绍性帖子,其中简要介绍了Task
侍者的使用方式SynchronizationContext
。SynchronizationContext
将请求上下文限制为仅一个线程。将此答案纳入博客文章中。
编辑: 这个问题看起来可能是相同的问题,但没有任何响应…
编辑: 在测试用例5中,任务似乎停留在WaitingForActivation
状态中。
我在.NET
4.5中使用System.Net.Http.HttpClient遇到了一些奇怪的行为-“等待”调用(例如)的结果httpClient.GetAsync(...)
将永远不会返回。
仅在使用新的异步/等待语言功能和Tasks API的某些情况下会发生这种情况-仅使用延续时,代码似乎总是可以工作。
这是一些重现此问题的代码-将其放入Visual Studio 11中的新“ MVC 4 WebApi项目”中,以暴露以下GET端点:
/api/test1
/api/test2
/api/test3
/api/test4
/api/test5 <--- never completes
/api/test6
此处的每个端点都返回相同的数据(来自stackoverflow.com的响应头),但/api/test5
永远不会完成。
复制代码:
public class BaseApiController : ApiController
{
/// <summary>
/// Retrieves data using continuations
/// </summary>
protected Task<string> Continuations_GetSomeDataAsync()
{
var httpClient = new HttpClient();
var t = httpClient.GetAsync("http://stackoverflow.com",HttpCompletionOption.ResponseHeadersRead);
return t.ContinueWith(t1 => t1.Result.Content.Headers.ToString());
}
/// <summary>
/// Retrieves data using async/await
/// </summary>
protected async Task<string> AsyncAwait_GetSomeDataAsync()
{
var httpClient = new HttpClient();
var result = await httpClient.GetAsync("http://stackoverflow.com",HttpCompletionOption.ResponseHeadersRead);
return result.Content.Headers.ToString();
}
}
public class Test1Controller : BaseApiController
{
/// <summary>
/// Handles task using Async/Await
/// </summary>
public async Task<string> Get()
{
var data = await Continuations_GetSomeDataAsync();
return data;
}
}
public class Test2Controller : BaseApiController
{
/// <summary>
/// Handles task by blocking the thread until the task completes
/// </summary>
public string Get()
{
var task = Continuations_GetSomeDataAsync();
var data = task.GetAwaiter().GetResult();
return data;
}
}
public class Test3Controller : BaseApiController
{
/// <summary>
/// Passes the task back to the controller host
/// </summary>
public Task<string> Get()
{
return Continuations_GetSomeDataAsync();
}
}
public class Test4Controller : BaseApiController
{
/// <summary>
/// Handles task using Async/Await
/// </summary>
public async Task<string> Get()
{
var data = await AsyncAwait_GetSomeDataAsync();
return data;
}
}
public class Test5Controller : BaseApiController
{
/// <summary>
/// Handles task by blocking the thread until the task completes
/// </summary>
public string Get()
{
var task = AsyncAwait_GetSomeDataAsync();
var data = task.GetAwaiter().GetResult();
return data;
}
}
public class Test6Controller : BaseApiController
{
/// <summary>
/// Passes the task back to the controller host
/// </summary>
public Task<string> Get()
{
return AsyncAwait_GetSomeDataAsync();
}
}
以上是大佬教程为你收集整理的使用await / async时,HttpClient.GetAsync(...)从不返回全部内容,希望文章能够帮你解决使用await / async时,HttpClient.GetAsync(...)从不返回所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。