C# ConcurrentQueue上的PLINQ不是';t多线程

C# ConcurrentQueue上的PLINQ不是';t多线程,c#,multithreading,postgresql,plinq,npgsql,C#,Multithreading,Postgresql,Plinq,Npgsql,我在C#计划中有以下PLINQ声明: arrestQueue和writeQueue都是 没有任何东西是并行运行的: 在运行时,CPU的总使用率约为30%,其他所有设备都在运行。我有8个内核(Core i7 720QM上的超线程有4个物理内核),而8个内核中的4个实际上根本没有利用率。其余的大约占40%-50% 磁盘使用率通常为0%,并且除了查询本地主机上的Postgres DB之外,没有任何网络使用(见下文) 如果我在geocodeThis.Geocode()中的某个地方添加断点,Visual

我在C#计划中有以下PLINQ声明:

arrestQueue
writeQueue
都是

没有任何东西是并行运行的:

  • 在运行时,CPU的总使用率约为30%,其他所有设备都在运行。我有8个内核(Core i7 720QM上的超线程有4个物理内核),而8个内核中的4个实际上根本没有利用率。其余的大约占40%-50%
  • 磁盘使用率通常为0%,并且除了查询本地主机上的Postgres DB之外,没有任何网络使用(见下文)
  • 如果我在
    geocodeThis.Geocode()
    中的某个地方添加断点,Visual Studio的Thread下拉列表只会显示[pid]主线程。它永远不会转到任何其他线程
  • 我正在使用连接到Postgres,每个线程对一个表运行一些SELECT查询。我正在运行pgAdmin III的服务器状态应用程序,它显示了pg_stat_活动。通过监视这一点和策略断点位置(见上文),我可以看到,对于所有运行
    geocodeThis.Geocode()
    的假定并发线程,应用程序打开的数据库连接从未超过1个。即使我在DB连接字符串中添加了Pooling=false,以强制连接不被池化,我在
    geocodeThis.Geocode()
    中也不会看到超过1个连接
  • Postgres表在WHERE子句中的每一列上都建立索引。即使它的索引很差,我也会期望大量的磁盘使用。如果博士后以任何其他方式支撑住局面,似乎它会浸泡一个核心

这似乎是一个简单的PLINQ案例研究,我不明白为什么没有并行运行。

并行集合上的Foreach仍然是一个单线程操作。AsParallel返回一个集合,该集合定义了一个.ForAll方法,该方法可以(但根据约定并不总是)并行运行。这方面的准则是:

arrestQueue.AsParallel().ForAll(arrest=>
    {
        Geocoder geocodeThis = new Geocoder(arrest);
        writeQueue.Enqueue(geocodeThis.Geocode());
        Console.Out.WriteLine("Enqueued " + ++k);
    });

您只需并行化
assertQueue
本身的枚举,然后将其“反分析”回普通
IEnumerable
。这一切都发生在
foreach
循环开始之前。然后将普通的
IEnumerable
与连续运行循环体的
foreach
一起使用

并行运行循环体的方法有很多,但首先想到的是使用
并行。ForEach

Parallel.ForEach(arrestQueue, arrest =>
    {
        Geocoder geocodeThis = new Geocoder(arrest);
        writeQueue.Enqueue(geocodeThis.Geocode());
        Console.Out.WriteLine("Enqueued " + ++k);
    });

这里还有第二个枚举——我第一次也错过了。但是在添加了这一点之后,它也起作用了。@Chris:
arrestQueue
属于
ConcurrentQueue
record类型。试着用虚拟类型编译你的(编辑过的)代码和原始海报的代码。确认,你是对的!将其作为第二个枚举阅读。据此编辑。@Chris:这是一个枚举。它只是
foreach(输入中的var项)收益返回项的枚举品种::-)谢谢这是有效的,但我很困惑:我如何在最初的PLINQ中进行分析?我看到你正在使用任务并行库而不是PLINQ。。。
Parallel.ForEach(arrestQueue, arrest =>
    {
        Geocoder geocodeThis = new Geocoder(arrest);
        writeQueue.Enqueue(geocodeThis.Geocode());
        Console.Out.WriteLine("Enqueued " + ++k);
    });