我正在使用ODP.NET,它不提供任何asych方法,如SQL驱动程序或其他Oracle驱动程序。
我有很多慢查询,有时我需要在一个MVC控制器调用上调用其中几个。所以我试图将它们包装在Task调用中。所以我正在考虑使用这种模式:
(这是一个有点人为的例子,我不会将相同的查询称为10次真实,这将是一些异构工作负载)
List<Task<DbDataReader>> list = new List<Task<DbDataReader>>(10);
for (int i = 0; i < 10; i++)
{
ERROR_LOG_PKG_DR package = new ERROR_LOG_PKG_DR();
//Could be a bunch of different queries.
//Returns a task that has the longrunningtask property set, so it's on it's own thread
list.Add(package.QUERY_ALL_ASYNC());
}
Task.WaitAll(list.ToArray());
这是任务:
public Task<DbDataReader> QUERY_ALL_ASYNC()
{
CancellationToken ct = new CancellationToken();
return Task.Factory.StartNew(_ =>
{
System.Diagnostics.Debug.WriteLine("InTask: Thread: " +
Thread.CurrentThread.ManagedThreadId);
System.Diagnostics.Debug.WriteLine("InTask: Is Background: " +
Thread.CurrentThread.IsBackground);
System.Diagnostics.Debug.WriteLine("InTask: Is ThreadPool: " +
Thread.CurrentThread.IsThreadPoolThread);
return QUERY_ALL<DbDataReader>();
}, null, ct,TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
这会引发10个线程。如果我想要一些像行为一样的线程池 - 即。一次只有大约4个并发线程 - 重用线程等,但我希望它在ASP.NET线程池之外(用于服务请求)
我该怎么做?
答案 0 :(得分:4)
如果您愿意牺牲Web应用程序的可伸缩性,可以使用SemaphoreSlim
来限制并行任务的数量:
const int MAX_PARALLEL_TASKS = 4;
DbDataReader GetData(CancellationToken token)
{
DbDataReader reader = ... // execute the synchronous DB API
return reader;
}
// this can be called form an async controller method
async Task ProcessAsync()
{
// list of synchronous methods or lambdas to offload to thread pool
var funcs = new Func<CancellationToken, DbDataReader>[] {
GetData, GetData2, ... };
Task<DbDataReader>[] tasks;
using (var semaphore = new SemaphoreSlim(MAX_PARALLEL_TASKS))
{
tasks = funcs.Select(async(func) =>
{
await semaphore.WaitAsync();
try
{
return await Task.Run(() => func(token));
}
finally
{
semaphore.Release();
}
}).ToArray();
await Task.WhenAll(tasks);
}
// process the results, e.g: tasks[0].Result
}
答案 1 :(得分:0)
我认为这就是你所需要的 - (msdn) How to: Create a Task Scheduler That Limits Concurrency。
短暂的想法是创建自定义TaskScheduler
,以限制同时运行任务的数量。
答案 2 :(得分:0)