for (int x = 0; x < blockCountX; x++)
{
for (int y = 0; y < blockCountY; y++)
{
//get blocks from image to new image and send to threaded processor
imageBlocks[x, y] = image.Clone(clipRectangle, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(ThreadedFromHeightMap));
t.Start(imageBlocks[x,y]);
clipRectangle.Offset(0, IMAGEBLOCKSIZE);
}
clipRectangle.Offset(IMAGEBLOCKSIZE, clipRectangle.Location.Y * -1);
}
break;
}
}
private void ThreadedFromHeightMap(object Image)
{
Bitmap image = (Bitmap)Image;
int width = image.Width;
int height = image.Height;
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
map.Hexes.Add(new Point(x, y), new Hex(image.GetPixel(x, y).B));
//tempHexes.Enqueue(new Hex(image.GetPixel(x, y).B));
}
}
}
我正在尝试从2048 x 2048 8bpp灰度高度图获取像素数据,并使用相应的高度值构建一个十六进制图。我将十六进制存储在Dictionary集合中。总而言之,该系列中有约400万个十六进制。
为了有效地做到这一点,我将图像分成256 x 256块,并将该图像传递给另一个线程,该线程将对其进行解析并将十六进制添加到集合中。这就是所有的事情。现在,我不再有一个以(0,0)为左上角的图像,而是现在有64个以(0,0)作为其左上角的图像块。但是我正在使用像素位置作为字典的索引。当第二个线程尝试添加索引为(0,0)的另一个值时,这将崩溃。
我该如何缓解这个问题?我考虑过要建立一个只包含一个图像成员和一个块编号成员的类,并将其传递给线程,这样我就可以根据线程正在处理的块来调整像素位置,但这似乎不是最佳选择。
(我意识到我正在使用的字典不是线程安全的。此后,我已经修复了该问题。)
最佳答案
我可以推荐几件事吗?
忘了image.GetPixel()了,它非常慢。直接与位图数据一起使用,算法的性能将大大提高,从而无需运行并行线程来提高其效率。请参见MSDN:http://msdn.microsoft.com/en-us/library/system.drawing.imaging.bitmapdata.aspx
如果您坚持使用并行线程,请使用线程池,而不要生成64个线程。 (请参见MSDN:http://msdn.microsoft.com/en-us/library/3dasc8as(v=vs.80).aspx)
如果您坚持要产生许多线程,请不要产生比CPU核心更多的线程。我不认为您的计算机上有64个内核,对吗?
如果您坚持要产生许多线程,那么您当然需要将每个图块的位置传递给该线程,以便您确切地知道重建大图时该图块应放置的位置。这不少于最优,这是必要的。