当前位置: 首页 > 编程语言 > C#

在ASP.Net应用程序中调用异步API分享

时间:2023-04-11 11:54:58 C#

在ASP.Net应用程序中调用异步API我对ASP.Net和异步编码有点陌生,所以请多多包涵。我已经用C#为我希望在ASP.Net应用程序中使用的WebAPI编写了一个异步包装器。下面是C#API包装器中的一个函数:publicasyncTaskgetProducts(){Productsproducts=newProducts();products.data=newList();字符串URL=client.BaseAddress+"/catalog/products";字符串additionalQuery="include=images";HttpResponseMessageresponse=awaitclient.GetAsync(URL+"?"+additionalQuery);如果(response.IsSuccessStatusCode){Productsp=awaitresponse.Content.ReadAsAsync();products.data.AddRange(p.data);while(response.IsSuccessStatusCode&&p.meta.pagination.links.next!=null){response=awaitclient.GetAsync(URL+p.meta.pagination.links.next+"&"+additionalQuery);如果(response.IsSuccessStatusCode){p=awaitresponse.Content.ReadAsAsync();products.data.AddRange(p.data);}}}返回JsonConvert.SerializeObject(产品,Formatting.Indented);我的ASP.Net应用程序中有一个WebMethod(它将使用来自Javascript文件的Ajax调用),它应该调用getProducts()函数。[WebMethod]publicstaticstringGetProducts(){BigCommerceAPIapi=getAPI();返回等待api.getProducts();}当然,这不行,因为WebMethod不是异步方法。我试图将其更改为这样的异步方法:[WebMethod]publicstaticasyncTaskGetProducts(){BigCommerceAPIapi=getAPI();返回等待api.getProducts();这段代码确实运行了,但是一旦它到达HttpResponseMessageresponse=awaitclient.GetAsync(URL+"?"+additionalQuery);在getProducts()函数中,调试器停止而不返回任何错误或数据。我错过了什么?如何从我的ASP应用程序中调用这个异步API?所以我实际上解决了一个与昨晚非常相似的问题。这很奇怪,因为此调用在.net4.5中有效。但是我们移动到4.5.2并且该方法开始死锁。我在async和asp.net上找到了这些有启发意义的文章(此处、此处、此处)。所以我修改了我的代码publicasyncTaskGetMemberByOrganizationId(stringorganizationId){vartask=await//ReSharperdisableonceUseStringInterpolation_httpClient.GetAsync(string.Format("mdm/rest/api/members/member?accountId={0}",organizationId)).ConfigureAwait(false);任务.EnsureSuccessStatusCode();varpayload=task.Content.ReadAsStringAsync();返回JsonConvert.DeserializeObject(awaitpayload.C??onfigureAwait(false),newJsonSerializerSettings{ContractNameResolver=newCamelCase});这解决了我的死锁问题。所以TLDR:在StephenCleary的文章概述中,我提到当您等待内置await时,await会捕获当前“上下文”,然后将其应用于异步方法的其余部分。“背景”究竟是什么?简单回答:如果您在UI线程上,那么它就是一个UI上下文。如果您正在响应ASP.NET请求,那么它就是一个ASP.NET请求上下文。否则,它通常是一个线程池上下文。复杂的答案:如果SynchronizationContext.Current不为null,则它是当前的SynchronizationContext。(UI和ASP.NET请求上下文是SynchronizationContext上下文)。否则,它是当前的TaskScheduler(TaskScheduler.Default是线程池上下文)。和解决方案在这种情况下,您想告诉等待者不要通过调用ConfigureAwait并传递false来捕获当前上下文我不确定ASP.NET中的[WebMethod]是什么。我记得它曾经是SOAPWeb服务,但现在没有人这样做了,因为我们有带有控制器的WebAPI,并且您可以在操作方法中使用async/await。测试代码的一种方法是使用.Result同步执行异步方法:[WebMethod]publicstaticstringGetProducts(){BigCommerceAPIapi=getAPI();返回api.getProducts().Result;正如maccettura在评论中指出的那样,这是一个同步调用,它锁定了线程。为确保没有死锁,请遵循Fran的建议并在getProducts()方法中的每个异步调用末尾添加.ConfigureAwait(false)。首先,按照惯例,GetProducts()应该命名为GetProductsAsync()。其次,async不会神奇地为其方法调用分配新线程。async-await主要利用天然的异步API,例如对数据库或远程Web服务的网络调用。使用Task.Run,??您可以明确使用线程池线程来执行您的委托。[WebMethod]publicstaticstringGetProductsAsync(){BigCommerceAPIapi=getAPI();返回Task.Run(()=>api.getProductsAsync().Result);查看这个链接是关于如何在ASP.NET中实现异步Web服务调用的项目示例以上是C#学习教程:在ASP.Net应用程序中调用异步API。如果对您有用,需要进一步了解C#学习教程,希望您多多关注——本文整理自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: