在ASP.Net MVC中长时间运行SQL查询的最佳实践
发布时间:2020-12-16 04:05:35 所属栏目:asp.Net 来源:网络整理
导读:我有一个动作方法,需要根据用户选择的日期完成15~52个长时间运行的SQL查询(所有这些查询都相似,每个查询需要5秒以上才能完成). 在做了大量研究之后,似乎在不阻塞ASP.Net线程的情况下执行此操作的最佳方法是使用async / await任务方法使用SQL查询: [HttpPost
我有一个动作方法,需要根据用户选择的日期完成15~52个长时间运行的SQL查询(所有这些查询都相似,每个查询需要5秒以上才能完成).
在做了大量研究之后,似乎在不阻塞ASP.Net线程的情况下执行此操作的最佳方法是使用async / await任务方法使用SQL查询: [HttpPost] public async Task<JsonResult> Action() { // initialization stuff // create tasks to run async SQL queries ConcurrentBag<Tuple<DateTime,List<long>>> weeklyObsIdBag = new ConcurrentBag<Tuple<DateTime,List<long>>>(); Task[] taskList = new Task[reportDates.Count()]; int idx = 0; foreach (var reportDate in reportDates) { //15 <= reportDates.Count() <= 52 var task = Task.Run(async () => { using (var sioDbContext = new SioDbContext()) { var historyEntryQueryable = sioDbContext.HistoryEntries .AsNoTracking() .AsQueryable<HistoryEntry>(); var obsIdList = await getObsIdListAsync( historyEntryQueryable,reportDate ); weeklyObsIdBag.Add(new Tuple<DateTime,List<long>>(reportDate,obsIdList)); } }); taskList[idx++] = task; } //await for all the tasks to complete await Task.WhenAll(taskList); // consume the results from long running SQL queries,// which is stored in weeklyObsIdBag } private async Task<List<long>> getObsIdListAsync( IQueryable<HistoryEntry> historyEntryQueryable,DateTime reportDate ) { //apply reportDate condition to historyEntryQueryable //run async query List<long> obsIdList = await historyEntryQueryable.Select(he => he.ObjectId) .Distinct() .ToListAsync() .ConfigureAwait(false); return obsIdList; } 进行此更改后,完成此操作所需的时间大大减少,因为现在我可以同时执行多个(15~52)异步SQL查询并等待它们完成而不是按顺序运行它们.但是,用户开始遇到很多超时问题,例如: (from Elmah error log) "Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached." "The wait operation timed out" 它是由线程饥饿引起的吗?我感觉我可能在线程池中使用了太多线程来实现我想要的东西,但我认为这应该不是问题,因为我使用async / await来阻止所有线程被阻塞. 如果事情不会以这种方式工作,那么执行多个长时间运行的SQL查询的最佳做法是什么? 解决方法
考虑限制正在执行的并发任务的数量,例如:
int concurrentTasksLimit = 5; List<Task> taskList = new List<Task>(); foreach (var reportDate in reportDates) { //15 <= reportDates.Count() <= 52 var task = Task.Run(async () => { using (var sioDbContext = new SioDbContext()) { var historyEntryQueryable = sioDbContext.HistoryEntries .AsNoTracking() .AsQueryable<HistoryEntry>(); var obsIdList = await getObsIdListAsync( historyEntryQueryable,reportDate ); weeklyObsIdBag.Add(new Tuple<DateTime,obsIdList)); } }); taskList.Add(task); if (concurrentTasksLimit == taskList.Count) { await Task.WhenAll(taskList); // before clearing the list,you should get the results and store in memory (e.g another list) for later usage... taskList.Clear(); } } //await for all the remaining tasks to complete if (taskList.Any()) await Task.WhenAll(taskList); 请注意,我将taskList更改为实际的List< Task>,它似乎更容易使用它,因为我们需要从列表中添加/删除任务. 此外,您应该在清除taskList之前获取结果,因为您将在以后使用它们. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- asp.net – Web Deploy和Parameters.xml:如何在多个项目之
- asp.net-mvc – 如何使这个ASP.NET MVC控制器更易于测试?
- asp.net – IIS 8中的URL中缺少.aspx
- asp.net-mvc – asp.net mvc 3中DataAnnotations的行为是否
- .net – 在控制器中创建子文件夹
- asp.net-mvc-3 – MVC3,Ninject和Ninject.MVC3问题
- ASP.NET中的<%%>(嵌入式代码块)
- asp.net-core – ASP.NET 5中RegisterObject / QueueBackgr
- asp.net – Stack Overflow的Mini Profiler
- ASP.NET MVC 3模型绑定资源
推荐文章
站长推荐
- asp.net – 如何停止所有cassini实例?
- asp.net – 如何使IRouteConstraint过滤器路由
- kendo-ui – 阻止kendo ui网格弹出编辑器关闭插入
- asp.net-mvc – 在Razor View中重命名mvc模型对象
- 使用WCF进行ASP.NET聊天
- asp.net – 如何确定字符串的第一个字符是否是VB
- asp.net-mvc – Chrome34忽略域名为“.cloudapp.
- asp.net – 无法加载文件或程序集’System.Net.H
- asp.net – COMException未知错误(0x80005000) –
- asp.net – 如何在razor viewengine中实现foreac
热点阅读