将非异步方法(进行Web调用)包装为异步

Osc*_*rEi 6 c# sharepoint async-await asp.net-web-api csom

我知道你应该只对非"CPU密集型"的东西使用异步,例如文件写入,Web调用等等,因此我也知道将每个方法包装成Task.Run类似的东西是没有意义的.

但是,当我知道某个方法进行Web调用时,我该怎么办,但它不提供异步接口.在这种情况下值得包装吗?

具体例子:

我在我的WebApi应用程序(服务器)中使用CSOM(客户端SharePoint对象模型),并希望获得SharePoint列表.

这通常是这样做的:

[HttpGet]
[Route("foo/{webUrl}")]
public int GetNumberOfLists(string webUrl)
{
    using (ClientContext context = new ClientContext(webUrl))
    {
        Web web = context.Web; 
        context.Load(web.Lists); 
        context.ExecuteQuery(); 

        return web.Lists.Count;
    }
}
Run Code Online (Sandbox Code Playgroud)

我想把它改成这样的东西:

[HttpGet]
[Route("foo/{webUrl}")]
public async Task<int> GetNumberOfLists(string webUrl)
{
    using (ClientContext context = new ClientContext(webUrl))
    {
        Web web = context.Web; 
        context.Load(web.Lists); 
        await Task.Run(() => clientContext.ExecuteQuery());

        return web.Lists.Count;
    }
}
Run Code Online (Sandbox Code Playgroud)

它是否有意义并且有帮助吗?据我了解,我只是创建/需要一个新的线程来执行查询("开销"),但至少请求线程将是空闲/准备好另一个请求(这将是好的).

但它是否值得,应该这样做吗?

如果是这样的话:微软不提供开箱即用的"异步"方法或他们只是不关心它并不奇怪吗?

编辑:更新以Task.Run按照评论中的建议使用.

Ste*_*ary 5

但是,当我知道某个方法进行Web调用时,我该怎么办,但它不提供异步接口.

不幸的是仍然有些常见 随着不同的库更新其API,它们最终将迎头赶上.

在这种情况下值得包装吗?

是的,如果您正在处理UI线程.否则,没有.

具体示例...在我的WebApi应用程序(服务器)中

然后,不,你不想包装Task.Run.正如我asyncASP.NET上的文章中所述:

您可以通过等待Task.Run开始一些后台工作,但这样做没有意义.实际上,这实际上会通过干扰ASP.NET线程池启发式来损害您的可伸缩性......作为一般规则,不要将工作排队到ASP.NET上的线程池.

Task.Run在ASP.NET上包装:

  • 干扰ASP.NET线程池启发式两次(现在通过线程然后稍后释放它).
  • 增加开销(代码必须切换线程).
  • 不释放线程(用于此请求的线程总数几乎等于仅调用同步版本).

据我了解,我只是创建/需要一个新的线程来执行查询("开销"),但至少请求线程将是空闲/准备好另一个请求(这将是好的).

是的,但你所做的只是跳线,没有任何好处.用于阻塞查询结果的线程是ASP.NET必须用来处理请求的一个线程,因此通过使用另一个线程来释放一个线程并不是一个很好的权衡.

微软不提供开箱即用的"异步"方法或者他们只是不关心它并不奇怪吗?

一些"较旧的"MS API还没有添加async版本.他们当然应该,但开发人员的时间是有限的资源.