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)

c#中线程的动态工作分配

如果你使用的是。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(任务并行库)