该站点由一个托管在4节点集群上的API(WEB API)站点和一个托管在另一个4节点集群上并调用该API的WEB站点组成。两者都是使用ASP.NET MVC5开发的,所有操作/方法都基于async-await方法。
在一些监视工具(如NewRelic)下运行站点、调查几个转储文件并分析工作进程之后,结果发现,在负载非常轻的情况下(例如16个并发用户),我们最终拥有大约900个线程,使用了100%的CPU并填满了IIS线程队列!
尽管我们通过引入大量缓存和性能修正将站点部署到了生产环境中,但我们团队中的许多开发人员认为,我们必须删除所有异步方法,并将API和web站点都隐藏到普通的web API和操作方法中,这些方法只返回操作结果。
public static async Task<T> GetApiResponse<T>(object parameters, string action, CancellationToken ctk)
{
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(BaseApiAddress);
var formatter = new JsonMediaTypeFormatter();
return
await
httpClient.PostAsJsonAsync(action, parameters, ctk)
.ContinueWith(x => x.Result.Content.ReadAsAsync<T>(new[] { formatter }).Result, ctk);
}
}
public async static Task<IList<DownloadType>> GetSupportedContentTypes()
{
string userAgent = Request.UserAgent;
var parameters = new { Util.AppKey, Util.StoreId, QueryParameters = new { UserAgent = userAgent } };
var taskResponse = await Util.GetApiResponse<ApiResponse<SearchResponse<ProductItem>>>(
parameters,
"api/Content/ContentTypeSummary",
default(CancellationToken));
return task.Data.Groups.Select(x => x.DownloadType()).ToList();
}
public async Task<ActionResult> DownloadTypes()
{
IList<DownloadType> supportedTypes = await ContentService.GetSupportedContentTypes();
这种方法有什么傻吗?注意,当我们将所有方法转换为非异步方法时,我们得到了更好的性能堆。
我可以看到这里至少有两件事出错了:
public static async Task<T> GetApiResponse<T>(object parameters, string action, CancellationToken ctk)
{
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(BaseApiAddress);
var formatter = new JsonMediaTypeFormatter();
return
await
httpClient.PostAsJsonAsync(action, parameters, ctk)
.ContinueWith(x => x.Result.Content
.ReadAsAsync<T>(new[] { formatter }).Result, ctk);
}
}
首先,传递给ContinueWith
的lambda正在阻塞:
x => x.Result.Content.ReadAsAsync<T>(new[] { formatter }).Result
x => {
var task = x.Result.Content.ReadAsAsync<T>(new[] { formatter });
task.Wait();
return task.Result;
};
return
await
httpClient.PostAsJsonAsync(action, parameters, ctk).ContinueWith(
x => x.Result.Content.ReadAsAsync<T>(new[] { formatter }),
ctk,
TaskContinuationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext()).Unwrap();
var x = await httpClient.PostAsJsonAsync(action, parameters, ctk);
return await x.Content.ReadAsAsync<T>(new[] { formatter });
如果我必须在同步上下文中调用一个异步方法,在这个上下文中不可能使用await,最好的方法是什么?
您几乎不需要将await
和continution混合使用。对于
,您应该坚持使用await
。基本上,如果使用async
,它必须“全程”异步。
对于服务器端ASP.NET MVC/Web API执行环境,这只是意味着控制器方法应该是异步
并返回任务
或任务<>
,请检查此选项。ASP.NET跟踪给定HTTP请求的挂起任务。只有完成所有任务后,请求才会完成。
对于客户端UI应用程序,可以从同步方法调用异步
方法。例如,您可以使用ContinueWith(action,taskScheduler.FromCurrentSynchronizationContext())
并从action
激发一个完成事件(如下所示)。
我一直试图理解C#中的Async/await和Task,但尽管看了youtube视频,阅读了文档,并参加了pluralsight课程,但一直失败得很厉害。 我希望有人能帮助回答这些稍微抽象的问题,帮助我的大脑摆脱困境。 1.为什么说async/await启用了一个“Asynchonrous”方法,而async关键字本身什么也不做,而await关键字添加了一个挂起点?添加挂起点不是强制方法同步操作,
我正在尝试将数据库调用移出控制器,以清理并使其可测试。当它们在控制器中时,一切都会顺利进行。我将它们移出控制器,并添加了一个异步,以确保我们等待。否则,我将调用的中的函数。现在,一旦我使用async/await,控制器中的函数就会认为没有用户,因为它没有等待。 有几个关于异步等待的SO问题,但我没有找到一个解决我的问题。我确实验证了返回了我的用户,并添加了控制台日志来显示路径。 节点猫鼬异步等待似
我试图在react/electron项目中使用async/await,但它不起作用。我想要的是获取docker容器状态列表。但是安慰。日志(列表)返回未定义的。 有人能帮我吗?:)
在实际应用中,我对 C# 中的异步和 await 方法进行了说明。请考虑以程,这是工作代码的简单版本: 助手.cs 功能控制器.cs processing.js 现在,问题是第三方服务的所需时间更少(例如:2秒),而所需的时间更多(例如:100秒)。进行两个ajax调用并使用异步和等待是为了呈现自我。屏幕上显示数据1,不要等到自己。Data2已被检索。不幸的是,这种情况没有发生,我必须等待100秒
我正试图将图像上传到firebase存储,但调用该函数时,未执行wait以获取url。我错过了什么? 看看这个其他主题,我发现问题可能是“然后”,但我如何设置代码以等待url? 异步/等待/然后飞镖/颤振 谢谢
我用webpack建立了一个浏览器umd库。 我正在侦听输入文件的onchange事件。当有人提交图像/文件时,它会将其转换为base64。我试图让它尽可能看起来不那么明显,所以我使用了promises和wait/asynchttps://blog.shovonhasan.com/using-promises-with-filereader/. 但是,有一个问题-当我调用convertToBase