C# C语言中线程的动态工作分配#

C# C语言中线程的动态工作分配#,c#,multithreading,parallel-processing,C#,Multithreading,Parallel Processing,我想知道如何设置一个类来为线程动态分配工作,最好是在C#中。我已经看过了光线跟踪器的解释,但我甚至没有看到对它的描述。我不想要太复杂的东西 我有一组任务太大了,无法平均分配给我的线程。我希望动态地将任务的一小部分分配给每个线程,然后当线程完成时,获得它们的结果并给它们更多的任务。我知道几年前我做过类似的事情,但我找不到这些笔记,也没有在谷歌或这里取得成功 任何帮助都将不胜感激 下面是我对伪代码的看法。它看起来并不漂亮,只是让你知道我在说什么 TaskList = ArrayList of n t

我想知道如何设置一个类来为线程动态分配工作,最好是在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)
TaskList=n个任务的数组列表
ResultList=线程结果的ArrayList
创建x个线程
整数任务已完成
while(任务完成
下面是一个用于管理简单工作队列的示例

当工作线程完成其当前项时,它将从工作队列中删除一个新项,处理该项,然后将其添加到输出队列

一个单独的使用者线程从输出队列中删除已完成的项目,并对它们进行处理

最后,我们必须等待所有工人完成(
Task.WaitAll(工人)
),然后才能将输出队列标记为已完成(
outputQueue.CompleteAdding()

此示例仅包含工作项的int;在实际代码中,您将使用封装工作的对象

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>();
    }
}
使用系统;
使用System.Collections.Concurrent;
使用系统线程;
使用System.Threading.Tasks;
名称空间演示
{
班级计划
{
静态void Main(字符串[]参数)
{
新程序().run();
}
无效运行()
{
int threadCount=4;
Task[]workers=新任务[threadCount];
Task.Factory.StartNew(消费者);
对于(int i=0;iworker(workerId));
工人[i]=任务;
task.Start();
}
对于(int i=0;i<100;++i)
{
WriteLine(“排队工作项{0}”,i);
inputQueue.Add(i);
睡眠(50);
}
Console.WriteLine(“停止添加”);
inputQueue.CompleteAdding();
Task.WaitAll(工人);
outputQueue.CompleteAdding();
控制台。WriteLine(“完成”);
Console.ReadLine();
}
无效工作程序(int-workerId)
{
WriteLine(“Worker{0}正在启动。”,workerId);
foreach(inputQueue.GetConsumingEnumerable()中的var workItem)
{
WriteLine(“Worker{0}正在处理项{1}”,workerId,workItem);
Thread.Sleep(100);//模拟工作。
outputQueue.Add(workItem);//输出完成的项。
}
WriteLine(“工作程序{0}正在停止。”,workerId);
}
无效消费者()
{
Console.WriteLine(“消费者正在启动”);
foreach(outputQueue.GetConsumingEnumerable()中的var workItem)
{
WriteLine(“消费者正在使用项{0}”,workItem);
睡眠(25);
}
Console.WriteLine(“消费者已完成”);
}
BlockingCollection inputQueue=新建BlockingCollection();
BlockingCollection outputQueue=新建BlockingCollection();
}
}

Plinq和数据流


,和-如果您可以使用.Net 4.5-如果您使用的是.Net 4.0+,那么也可以使用Parallel.For方法。它启动它认为并行处理循环所需的任意多个线程。很好的一点是,它为您管理线程并监视它们。以下是一个平行的操作介绍:


您还应该研究任务并行库在.NET4.0中引入的其他构造。它有很多非常简洁的多线程助手,使多线程比启动和管理自己的线程容易得多。您可以在此处看到MSDN文档:

您应该查看或如果您可以使用.Net 4.5,您也可以查看,它是为这种精确的场景而设计的。您所描述的是一个线程池。C#从2.0版开始就有了一个线程池,尽管它在4.0版中通过添加TPL和其他构建在线程池之上的高级并行编程工具大大扩展了它的功能。在编写自己的线程池之前,请确保这些线程不能满足您的需要。