这一切都发生在Windows服务中。
我有Queue<T>
(实际上是ConcurrentQueue<T>
)等待处理的项目。但是,我不想一次只处理一个,我想同时处理n个项目,其中n是一个可配置的整数。
如何使用任务并行库进行此操作?
我知道TPL会代表开发人员对集合进行并发处理,但不确定这是否是我所追求的功能。我是多线程和TPL的新手。
答案 0 :(得分:4)
使用BlockingCollection<T>
代替ConcurrentQueue<T>
,然后您可以启动任意数量的使用者主题并使用Take
的{{1}}方法。如果集合为空,BlockingCollection
方法将自动在调用程序线程中阻塞,等待添加项,否则线程将并行使用所有队列项。但是,由于您的问题提到了使用TPL,因此Take
使用Parallel.ForEach
检查this帖子时会遇到一些问题,以获取更多详细信息。所以你必须管理自己的消费者线程的创建。 BlockingCollection
或new Thread(/*consumer method*/)
...
答案 1 :(得分:4)
这是一个涉及为TaskFactory
创建扩展方法的想法。
public static class TaskFactoryExtension
{
public static Task StartNew(this TaskFactory target, Action action, int parallelism)
{
var tasks = new Task[parallelism];
for (int i = 0; i < parallelism; i++)
{
tasks[i] = target.StartNew(action);
}
return target.StartNew(() => Task.WaitAll(tasks));
}
}
然后你的调用代码如下所示。
ConcurrentQueue<T> queue = GetQueue();
int n = GetDegreeOfParallelism();
var task = Task.Factory.StartNew(
() =>
{
T item;
while (queue.TryDequeue(out item))
{
ProcessItem(item);
}
}, n);
task.Wait(); // Optionally wait for everything to finish.
这是使用Parallel.ForEach
的另一个想法。这种方法的问题在于您的并行度可能不一定得到尊重。您只是指出允许的最大金额而不是绝对金额。
ConcurrentQueue<T> queue = GetQueue();
int n = GetDegreeOfParallelism();
Parallel.ForEach(queue, new ParallelOptions { MaxDegreeOfParallelism = n },
(item) =>
{
ProcessItem(item);
});
答案 2 :(得分:1)
我还建议您使用BlockingCollection
而不是直接使用ConcurrentQueue
。
以下是一个例子:
public class QueuingRequestProcessor
{
private BlockingCollection<MyRequestType> queue;
public void QueuingRequestProcessor(int maxConcurrent)
{
this.queue = new BlockingCollection<MyRequestType>(maxConcurrent);
Task[] consumers = new Task[maxConcurrent];
for (int i = 0; i < maxConcurrent; i++)
{
consumers[i] = Task.Factory.StartNew(() =>
{
// Will wait when queue is empty, until CompleteAdding() is called
foreach (var request in this.queue.GetConsumingEnumerable())
{
Process(request);
}
});
}
}
public void Add(MyRequest request)
{
this.queue.Add(request);
}
public void Stop()
{
this.queue.CompleteAdding();
}
private void Process(MyRequestType request)
{
// Do your processing here
}
}
请注意,构造函数中的maxConcurrent
定义了将同时处理多少个请求。