c#中线程的动态工作分配
本文关键字:工作 分配 动态 线程 | 更新日期: 2023-09-27 18:11:47
我想知道如何设置一个可以动态分配线程工作的类,最好是在c#中。我看过射线追踪器的解释,但我甚至没有看到它看起来是什么样子的描述。我不想要太复杂的东西。
我有一组任务太大了,不能均匀地分配给我的线程。我想动态地将任务的一小部分分配给每个线程,然后当线程完成时,获取它们的结果并给它们更多的任务。我知道我几年前做过类似的事情,但我找不到那些笔记,我在谷歌或这里也没有成功。
任何帮助都将是非常感激的。
下面的是我对它在伪代码中的样子的想法。它不会看起来很漂亮,但只是让你知道我在说什么。
TaskList = ArrayList of n tasks
ResultList = ArrayList of thread results
create x threads
integer TasksCompleted
while(TasksCompleted < TaskList.size){
thread = next available thread in pool
ResultList.add(thread.results)
tasksCompleted += thread.numOfTasks
thread.doWork(Next set of Tasks)
}
clean up threads
processResults(ResultList)
如果你使用的是。net 4.0+,那么你可以使用Parallel。的方法。它启动尽可能多的线程,它认为需要并行处理循环。它的好处是可以为您管理线程并监视它们。下面是如何介绍并行:http://msdn.microsoft.com/en-us/library/dd460713.aspx
您还应该查看。net 4.0中任务并行库引入的其他结构。它有很多非常简洁的多线程帮助程序,使多线程比启动和管理您自己的线程容易得多。你可以在这里看到MSDN文档:http://msdn.microsoft.com/en-us/library/dd537609.aspx
下面是使用BlockingCollection
管理一个简单工作队列的示例。
当一个工作线程完成了它当前的项目,它将从工作队列中删除一个新项目,处理该项目,然后将其添加到输出队列中。
一个单独的消费者线程从输出队列中删除已完成的项目,并对它们进行处理。
在结束时,我们必须等待所有的工人完成(Task.WaitAll(workers)
),然后才能将输出队列标记为完成(outputQueue.CompleteAdding()
)。
这个例子只有工作项的整型;在实际代码中,您将使用封装工作的对象。
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
new Program().run();
}
void run()
{
int threadCount = 4;
Task[] workers = new Task[threadCount];
Task.Factory.StartNew(consumer);
for (int i = 0; i < threadCount; ++i)
{
int workerId = i;
Task task = new Task(() => worker(workerId));
workers[i] = task;
task.Start();
}
for (int i = 0; i < 100; ++i)
{
Console.WriteLine("Queueing work item {0}", i);
inputQueue.Add(i);
Thread.Sleep(50);
}
Console.WriteLine("Stopping adding.");
inputQueue.CompleteAdding();
Task.WaitAll(workers);
outputQueue.CompleteAdding();
Console.WriteLine("Done.");
Console.ReadLine();
}
void worker(int workerId)
{
Console.WriteLine("Worker {0} is starting.", workerId);
foreach (var workItem in inputQueue.GetConsumingEnumerable())
{
Console.WriteLine("Worker {0} is processing item {1}", workerId, workItem);
Thread.Sleep(100); // Simulate work.
outputQueue.Add(workItem); // Output completed item.
}
Console.WriteLine("Worker {0} is stopping.", workerId);
}
void consumer()
{
Console.WriteLine("Consumer is starting.");
foreach (var workItem in outputQueue.GetConsumingEnumerable())
{
Console.WriteLine("Consumer is using item {0}", workItem);
Thread.Sleep(25);
}
Console.WriteLine("Consumer is finished.");
}
BlockingCollection<int> inputQueue = new BlockingCollection<int>();
BlockingCollection<int> outputQueue = new BlockingCollection<int>();
}
}
Plinq and Dataflow
你还应该看看Plinq,如果你可以使用。net 4.5,还有Dataflow(任务并行库)