2015-03-02 120 views
0

on C#Net 2.0多线程填充阵列

代码的工作速度稍慢于单线程版本。 xDiff = 2100,yDiff = 2000;多线程(代码)中单线程约为14秒,多线程约为16秒。有些事情一定是错的。 我需要填充结果数组。只有一次在数组节点上写入数据,没有读取,所以它应该适用于多线程。

double[,] result = new double[xDiff, yDiff]; 
int threadCount = Environment.ProcessorCount; 
ManualResetEvent finished = new ManualResetEvent(false); 
int perthread = xDiff/threadCount; 
int left = xDiff % threadCount; 
int toProcess = threadCount; 
int s = 0; 
int e = left; 
for (int ii = 0; ii < threadCount; ii++) 
{ 
    ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state) 
    { 
     for (int x = s; x < e; x++) 
     for (int y = 0; y < yDiff; y++) 
     { 
      result[x, y] = DoWork((xStart + x), (yStart + y), p) 
     } 
     if (System.Threading.Interlocked.Decrement(ref toProcess) == 0) finished.Set(); 
    }), null); 
    s = e; 
    e += perthread; 
} 
finished.WaitOne(); 
return result; 

xStart,yStart是双倍,p是一个大类。 DoWork函数只调用p的某些函数,但不能写入/更改类上的任何数据。

简而言之,结果[x,y] = DoWork((xStart + x),(yStart + y),p); 我需要尽可能快地填充数组。我该怎么做?

+0

DoWork的是做一些阻塞操作?如果是这样,您最好每次打电话给DoWork排队一个新的工作项目。请注意,QueueUserWorkItem实际上不会创建新线程 – 2015-03-02 10:39:57

+0

请考虑使用Parallel类中的现成循环之一。你的情况看起来并不特别。 – usr 2015-03-02 12:02:49

+0

@usr我首先忽略了,但OP使用.NET 2.0。 – CodesInChaos 2015-03-02 12:03:45

回答

2

我认为这里的问题是变量se是在线程外被修改的闭包,所以线程得到了错误的值并且使用了错误的范围。

要查看是否是这样的话,尝试添加一个Console.WriteLine()Trace.WriteLine()打印出来的se线程(调用QueueUserWorkItem()后)内的值来看看这是发生了什么。

为了解决这个问题,修改后的封锁复制到临时变量,并使用那些线程,就像这样:

for (int ii = 0; ii < threadCount; ii++) 
{ 
    int ts = s; // Copy them outside the loop. 
    int te = e; 
    ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state) 
    { 
     for (int x = ts; x < te; x++) // Use the copy here. 

另见Access to Modified Closure

+0

最坏情况:所有工人都填满整个阵列 – 2015-03-02 11:14:58

+0

谢谢,我错过了。当我检查s和e时,所有线程都试图填充所有数组。 – user1708062 2015-03-02 12:09:55