2017-03-02 64 views
5

我知道您应该只对非“CPU密集型”的东西使用异步,例如,文件写入,网络电话等,因此我也知道把每种方法都包装进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; 
    } 
} 

而且我认为它更改为这样的事情:

[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; 
    } 
} 

是否有意义和帮助?据我了解,我只是创建/需要一个新的线程来执行查询(“开销”),但至少请求线程将自由/准备好另一个请求(这很好)。

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

如果是这样的话: 微软不提供“异步”方法或者他们不关心它是不是很奇怪?

编辑: 更新为使用Task.Run如在评论中所建议的。

+0

不要使用'Task.Factory.StartNew',使用'Task.Run'。至于调用* *的SharePoint,上下文有'ExecuteQueryAsync'方法,它可以适用于返回任务 –

+0

我没有在我使用我的CSOM库'ExecuteQueryAsync' ....其他的事情我改变。 –

+0

刚刚通过nuget上传到'Microsoft.SharePointOnline.CSOM,16.1.6216' - 仍然没有'ExecuteQueryAsync'。 –

回答

3

但是我应该怎么做当我知道一个方法进行网络调用,但它不提供异步接口。

不幸的是仍然有点常见。随着不同的图书馆更新他们的API,他们最终会赶上。

在这种情况下是否值得包装它?

是的,如果你正在处理一个UI线程。否则,不。

具体的例子......在我的WebAPI的应用程序(服务器)

然后,不,你不希望在Task.Run包。正如我在article on async ASP.NET中提到的:

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

包装与Task.Run在ASP.NET:

  • 与ASP.NET线程池的启发式干扰两次(通过采取线程现在再后来释放它)。
  • 增加开销(代码必须切换线程)。
  • 不腾出一个线程(用于此请求的线程总数几乎等于只是调用同步版本)。

据我了解,我只是创建/需要一个新的线程来执行查询(“开销”),但至少请求的线程将免费/准备好另一个请求(这将是很好的) 。

是的,但你所做的只是跳线,没有任何好处。用于阻止查询结果的线程是ASP.NET必须用来处理请求的线程之一,因此通过消耗另一个线程来释放一个线程并不是一个好的折衷。

微软不提供开箱即用的“异步”方法或者他们不关心它是不是很奇怪?

一些“旧”MS API尚未添加到async版本。他们肯定应该,但开发人员时间是一个有限的资源。

+0

完美的答案,正是我“寻找” - 谢谢你! –

0

这是我个人对您的问题的看法,对我而言,上述方式并非必需。当我们在IIS中托管您的API时,服务器会从它在服务器中的线程池中分配一个线程。 IIS还具有maxConcurrentRequestsPerCPU maxConcurrentThreadsPerCPU的设置。您可以设置这些值来服务请求,而不是自己处理请求。