在ASP.Net MVC中长时间运行SQL查询的最佳实践
发布时间:2020-05-30 11:39:17 所属栏目: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 – 使用NLog记录当前页面的URL
- asp.net – 您是否将助手类存储在单独的程序集中?
- asp.net-mvc – 具有多个应用程序的ASP.NET标识
- asp.net-mvc – 本地化数据注释默认消息([必需] [StringLen
- ASP.net没有为某些用户代理生成javascript
- asp.net-mvc-3 – 坚持使用asp.net mvc 3.0脚手架,以防多对
- asp.net-mvc – ASP.NET MVC – 结合Json结果与ViewResult
- asp.net-web-api – oData $count不能与web api 4中的Entit
- asp.net – 如何忽略正则表达式的情况?
- ASP.Net Checkbox值在回发错误?
推荐文章
站长推荐
- 为什么ASP.NET回发时请求cookie属性为null或不正
- asp.net-mvc-3 – 如何使用DropdownList助手正确
- asp.net-mvc – 重定向页面的TempData?
- asp.net – 如何在iframe中提交后刷新iframe父页
- asp.net – Vs html
- asp.net-mvc-3 – 将AuthorizeAttribute应用于控
- ASP.NET Web API为单个路由定制IHttpControllerS
- asp.net – 对象不是垃圾回收,但不包含gcroot
- asp.net – 使用Html.TextBox添加css类
- asp.net – 如何在IIS7中为HttpHandler注册多个路
热点阅读
