程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了使用await / async时,HttpClient.GetAsync(...)从不返回大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决使用await / async时,HttpClient.GetAsync(...)从不返回?

开发过程中遇到使用await / async时,HttpClient.GetAsync(...)从不返回的问题如何解决?下面主要结合日常开发的经验,给出你关于使用await / async时,HttpClient.GetAsync(...)从不返回的解决方法建议,希望对你解决使用await / async时,HttpClient.GetAsync(...)从不返回有所启发或帮助;

您正在滥用API。

情况就是这样:在ASP.NET中,一次只有一个线程可以处理一个请求。如果有必要,您可以执行一些并行处理(从线程池中借用其他线程),但是只有一个线程具有请求上下文(其他线程没有请求上下文)。

这由ASP.NET管理SynchronizationContext

默认情况下,当您使用awaita时Task,该方法将在捕获到的对象SynchronizationContext(或没有捕获TaskScheduler到的对象SynchronizationContext)上继续。通常,这就是您想要的:异步控制器操作将执行await某些操作,并且在恢复操作时,将在请求上下文中恢复操作。

因此,这就是test5失败的原因:

  • Test5Controller.Get执行AsyncAwait_GetSomeDataAsync(在ASP.NET请求上下文中)。
  • AsyncAwait_GetSomeDataAsync执行httpClIEnt.GetAsync(在ASP.NET请求上下文中)。
  • http请求被发送出去,并httpClIEnt.GetAsync返回一个uncompleted Task
  • AsyncAwait_GetSomeDataAsync等待Task; 由于未完成,因此AsyncAwait_GetSomeDataAsync返回uncompleted Task
  • Test5Controller.Get 当前线程,直到Task完成为止。
  • http响应进入,Task并由返回httpClIEnt.GetAsync完成。
  • AsyncAwait_GetSomeDataAsync尝试在ASP.NET请求上下文中恢复。但是,在该上下文中已经有一个线程:该线程在中被阻塞Test5Controller.Get
  • 僵局。

这就是其他方法起作用的原因:

  • test1test2test3):在ASP.NET请求上下文 之外Continuations_GetSomeDataAsync调度到线程池的继续。这使得返回者可以完成而不必重新输入请求上下文。 __Task``Continuations_GetSomeDataAsync
  • test4test6):由于Task正在 等待 ,因此不会阻止ASP.NET请求线程。AsyncAwait_GetSomeDataAsync当准备好继续时,这允许使用ASP.NET请求上下文。

这是最佳做法:

  1. 在您的“库” async方法中,请ConfigureAwait(false)尽可能使用。在你的情况,这将改变AsyncAwait_GetSomeDataAsyncvar result = await httpClIEnt.GetAsync("http://stackoverflow.com", httpCompletionoption.ResponseheadersRead).ConfigureAwait(false);
  2. 不要阻塞Tasks;它是async一路下滑。换句话说,请使用await代替GetResultTask.Result并且Task.Wait也应替换为await)。

这样,您将获得两个好处:延续(AsyncAwait_GetSomeDataAsync方法的其余部分)在基本线程池线程上运行,该线程不必输入ASP.NET请求上下文;控制器本身是async(不会阻塞请求线程)。

更多信息:

  • 我的async/ await介绍性帖子,其中简要介绍了Task侍者的使用方式SynchronizationContext
  • 在异步/等待FAQ,其中进入的背景下更详细。另请参见等待,UI和死锁!天啊!即使您使用的是ASP.NET而不是UI,这 适用于此,因为ASP.NET一次SynchronizationContext将请求上下文限制为仅一个线程。
  • 此MSDN论坛帖子。
  • Stephen Toub 演示了此死锁(使用UI),Lucian Wischik也进行了演示。

将此答案纳入博客文章中。

解决方法

编辑: 这个问题看起来可能是相同的问题,但没有任何响应…

编辑: 在测试用例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永远不会完成。

我是否在HttpClient类中遇到错误,还是我在某种程度上滥用了API?

复制代码:

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,请注明来意。
标签: