我有一个Windows服务,需要从数据库中选择作业并需要对其进行处理。
在这里,每个作业都是一个扫描过程,大约需要10分钟才能完成。
我是Task Parallel Library的新手。我已通过以下方式作为示例逻辑实现:
Queue queue = new Queue();
for (int i = 0; i < 10000; i++)
{
queue.Enqueue(i);
}
for (int i = 0; i < 100; i++)
{
Task.Factory.StartNew((Object data ) =>
{
var Objdata = (Queue)data;
Console.WriteLine(Objdata.Dequeue());
Console.WriteLine(
"The current thread is " + Thread.CurrentThread.ManagedThreadId);
}, queue, TaskCreationOptions.LongRunning);
}
Console.ReadLine();
但是,这会创建很多线程。由于循环重复100次,因此它正在创建100个线程。
创建大量并行线程是否正确?
有什么方法可以将线程数限制为10(并发级别)?
最佳答案
分配新的Threads
时要记住的一个重要因素是,操作系统必须分配多个逻辑实体才能运行该当前线程:
包括线程的上下文,cpu寄存器等
存储
模式
除此之外,可能运行的并发
Threads
的数量取决于计算机要打包的内核数,并且创建大于计算机所拥有的内核数的线程数量将开始导致Context Switching
,从长远来看,这会导致Producer-Consumer
。可能会减慢您的工作速度。因此,经过漫长的介绍之后,您将了解到好东西。我们实际上想要做的是限制正在运行的线程数,并尽可能地重用它们。
对于这种工作,我将使用基于
Block
模式的TPL Dataflow。只是可以做的一个小例子:// a BufferBlock is an equivalent of a ConcurrentQueue to buffer your objects
var bufferBlock = new BufferBlock<object>();
// An ActionBlock to process each object and do something with it
var actionBlock = new ActionBlock<object>(obj =>
{
// Do stuff with the objects from the bufferblock
});
bufferBlock.LinkTo(actionBlock);
bufferBlock.Completion.ContinueWith(t => actionBlock.Complete());
您可以为每个
ExecutionDataflowBlockOptions
传递一个Bounded Capacity
,它可以限制MaxDegreeOfParallelism
(BufferBlock中对象的数量),而ojit_code则告诉该块您可能需要的最大并发数量。有一个很好的示例here可以帮助您入门。
关于c# - 这是正确的执行方式吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24380518/