我需要向我的数据库执行大量数据插入。我可以使用限制并发操作数量的节流调度程序以多线程方式实现代码。每 M
行,形成一个 block 并将其作为原子操作插入到数据库中。由于数据库比读取和解析数据文件慢,因此会发生多个并发操作。我经常使用多线程来实现这个模型。
如果我决定使用await/async( Entity Framework 支持异步编程)来实现我的代码,我如何确保执行的并发任务不超过N个(即转到数据库)同时?
在我最初的设计中,我实例化了一个 List<Task>
,一旦我读取要原子插入的数据 block ,就添加新任务,然后让我的方法在 await
之后返回完成所有任务。设计时的问题是并发数Task
s(以及内存占用)将会爆炸,因为任务的输入速度比大数据文件的完成速度快。
我正在考虑使用SemaphoreSlim
,但我对异步编程(与多线程不同)经验很少。所以我问这个问题是为了获得有关最佳实践的反馈(如果有的话)。
最佳答案
The design-time issue is that the number of concurrent Tasks (and thus memory footprint) are going to explode because tasks are fed faster than they complete for big data files. I was thinking about using a SemaphoreSlim
是的,SemaphoreSlim
是限制并发异步操作的合适选择:
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(10);
async Task ThrottledWorkAsync()
{
await _semaphore.WaitAsync();
try
{
await WorkAsync();
}
finally
{
_semaphore.Release();
}
}
但是...
If instead I decide to implement my code using await/async (Entity Framework supports asynchronous programming), how can I make sure that no more than N concurrent tasks execute (i.e. go to database) at the same time?
需要注意的一件事是, Entity Framework 虽然支持异步 API,但每个请求仍然需要一个连接。因此,同一个 DbContext 不能有多个并发异步请求;您需要为每个并发请求创建一个单独的连接(或者至少由并发请求“借用”的 N 个连接)。
关于c# - 限制并发System.Threading.Tasks.Task的数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40723104/