我正在尝试创建生产者/消费者TPL数据流过程。作为其中的一部分,我将为不同的id范围创建多个生产者任务,这些任务将生成要处理的数据记录。因此,我计划限制将连接到数据库以获取数据并同时处于活动状态的线程的数量。
但是,提取数据并将其发送到BufferBlock的方法具有返回类型,因此我可以获取提取的记录数。因此,我无法从SemaphoreSlim类中找出在哪里调用Release方法,但仍然可以获得返回值?下面是我正在使用的示例代码。有人可以建议任何解决方法吗?
private Task<KeyRange>[] DataExtractProducer(ITargetBlock<DataRow[]> targetBuffer, ExtractQueryConfiguration QueryConf)
{
CancellationToken cancelToken = cancelTokenSrc.Token;
var tasks = new List<Task<KeyRange>>();
int taskCount = 0;
int maxThreads = QueryConf.MaxThreadsLimit > 0 ? QueryConf.MaxThreadsLimit : DataExtConstants.DefaultMaxThreads;
using (SemaphoreSlim concurrency = new SemaphoreSlim(maxThreads))
{
foreach (KeyRange range in keyRangeList)
{
concurrency.WaitAsync();
var task = Task.Run(() =>
{
Console.WriteLine(MsgConstants.StartKeyRangeExtract, QueryConf.KeyColumn, range.StartValue, range.EndValue);
//concurrency.Release();
return GetDataTask(targetBuffer, range, QueryConf.ExtractQuery);
}, cancelToken);
tasks.Add(task);
taskCount++;
}
}
Console.WriteLine(MsgConstants.TaskCountMessage, taskCount);
return tasks.ToArray<Task<KeyRange>>();
}
编辑:我也尝试了这种变体。但这似乎不起作用。我尝试使用20个限制。但是我看到50个以上的数据库连接断开了。最终,由于没有节流的连接,我的内存消耗很高。
using (SemaphoreSlim concurrency = new SemaphoreSlim(maxThreads))
{
foreach (KeyRange range in keyRangeList)
{
concurrency.WaitAsync();
var task = Task.Run(() =>
{
Console.WriteLine(MsgConstants.StartKeyRangeExtract, QueryConf.KeyColumn, range.StartValue, range.EndValue);
var temptask = await GetDataTask(targetBuffer, range, QueryConf.ExtractQuery);
concurrency.Release();
return temptask;
}, cancelToken);
tasks.Add(task);
taskCount++;
}
}
谢谢!