使用c#任务从SQL获取行
我的桌子上大约有300万行。我有一个控制台应用程序来获取所有行并处理这些行。我想使用TPL一次获取1000行并执行我的处理逻辑。我可以有以下逻辑,在ProcessRowsForPage方法中,我将根据页码获取记录使用c#任务从SQL获取行,c#,.net,task-parallel-library,C#,.net,Task Parallel Library,我的桌子上大约有300万行。我有一个控制台应用程序来获取所有行并处理这些行。我想使用TPL一次获取1000行并执行我的处理逻辑。我可以有以下逻辑,在ProcessRowsForPage方法中,我将根据页码获取记录 int totalRecordsCount = GetCount(); int pagecount = totalRecordsCount/1000; for (int j= 0; j <= pagecount; j++) { var pageNo= j; var
int totalRecordsCount = GetCount();
int pagecount = totalRecordsCount/1000;
for (int j= 0; j <= pagecount; j++)
{
var pageNo= j;
var t = Task.Factory.StartNew(() =>
{
ProcessRowsForPage(pageNo);
});
tasks.Add(t);
}
int totalRecordsCount=GetCount();
int pagecount=totalRecordsCount/1000;
对于(int j=0;j
{
ProcessRowsForPage(页码);
});
任务。添加(t);
}
可能是,这很奇怪,但是有没有一种方法可以在不计算总数的情况下创建任务。我想使用类似do while循环的方法,在没有更多行可提取时停止创建任务如果使用某种类型的池,您可以这样做,而不是生成数百万个任务,这是一个坏主意 在一个数组中创建3个(例如)任务,并启动它们 当一个任务完成时,如果有更多行,请将其重新设置 一旦任务不再返回数据,停止设置,等待所有任务完成,然后完成 例如:
TASK1 > GetNext100Rows(0)
TASK2 > GetNext100Rows(100)
TASK3 > GetNext100Rows(200)
如果Task2首先完成,请重新启动它:
TASK1 > GetNext100Rows(0) [Processing]
TASK2 > GetNext100Rows(300) [Processing]
TASK3 > GetNext100Rows(200) [Processing]
继续重新启动所有已完成的任务,每次增加100
最后,当任务不再返回数据时,等待所有剩余线程完成
这要求您的任务能够返回或指示它没有更多的数据,例如通过设置标志变量或返回对象。如果您使用某种类型的池,您可以这样做,而不是产生可能数以百万计的任务,这是一个坏主意 在一个数组中创建3个(例如)任务,并启动它们 当一个任务完成时,如果有更多行,请将其重新设置 一旦任务不再返回数据,停止设置,等待所有任务完成,然后完成 例如:
TASK1 > GetNext100Rows(0)
TASK2 > GetNext100Rows(100)
TASK3 > GetNext100Rows(200)
如果Task2首先完成,请重新启动它:
TASK1 > GetNext100Rows(0) [Processing]
TASK2 > GetNext100Rows(300) [Processing]
TASK3 > GetNext100Rows(200) [Processing]
继续重新启动所有已完成的任务,每次增加100
最后,当任务不再返回数据时,等待所有剩余线程完成
这要求您的任务能够返回或指示它没有更多的数据,例如通过设置标志变量或返回对象。对于这种情况,您最好选择 为此,您需要以下组件:
- 一个
或其他类型的东西,可以从数据库中传输数据SqlDataReader
- 批处理大小为1000的a
- 将调用
方法的ProcessRows
batchBlock.LinkTo(actionBlock, new DataflowLinkOptions { PropagateCompletion = true });
之后,从dataReader
Post
行到BatchBlock
:
while(reader.Read())
{
var item = ConvertRow(reader);
batchBlock.Post(item);
}
// When you get here you've read all the data from the database
// tell the pipeline that no more data is coming
batchBlock.Complete();
这将负责处理。如果希望在管道处理完所有项目后收到通知,请使用ActionBlock
的Completion
属性获得通知
actionBlock.Completion.ContinueWith(prev => {Console.WriteLine("Finished.");}).
在这种情况下,你最好接受 为此,您需要以下组件:
- 一个
或其他类型的东西,可以从数据库中传输数据SqlDataReader
- 批处理大小为1000的a
- 将调用
方法的ProcessRows
batchBlock.LinkTo(actionBlock, new DataflowLinkOptions { PropagateCompletion = true });
之后,从dataReader
Post
行到BatchBlock
:
while(reader.Read())
{
var item = ConvertRow(reader);
batchBlock.Post(item);
}
// When you get here you've read all the data from the database
// tell the pipeline that no more data is coming
batchBlock.Complete();
这将负责处理。如果希望在管道处理完所有项目后收到通知,请使用ActionBlock
的Completion
属性获得通知
actionBlock.Completion.ContinueWith(prev => {Console.WriteLine("Finished.");}).
如果没有计数,任务如何知道它已到达最后一页?它将不得不询问上一个任务,但上一个任务可能尚未完成。是的。我认为,除非我知道总计数,否则我认为不可能创建多个任务。您可以使用ConcurrentQueue,一次出列1000个。如果没有计数,任务如何知道它已到达最后一页?它将不得不询问上一个任务,但上一个任务可能尚未完成。是的。我认为,除非我知道总数,否则我认为不可能创建多个任务。您可以使用ConcurrentQueue,一次出列1000个任务。