我有以下代码:
private static void SplitTilesRecursive(Image original, int level)
{
int mapWidth = GetMapWidth(level);
int tilesOnSide = mapWidth/TileSize;
using (Image resized = ResizeImage(original, new Size(mapWidth, mapWidth)))
{
for (int x = 0; x < tilesOnSide; x++)
for (int y = 0; y < tilesOnSide; y++)
{
CropAndSaveTile(resized, x, y, level);
}
}
if (level > 0)
SplitTilesRecursive(original, level - 1);
}
private static void CropAndSaveTile(Image image, int x, int y, int level)
{
var info = (CropInfo) o;
var cropArea = new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize);
using (var bmpImage = new Bitmap(image))
using (Bitmap bmpCrop = bmpImage.Clone(cropArea, bmpImage.PixelFormat))
{
string filename = String.Format(TileFilename, level, x, y);
// the Portable Network Graphics (PNG) encoder is used implicitly
bmpCrop.Save(Path.Combine(OutputDir, filename));
Console.WriteLine("Processed " + filename);
}
}
方法CropAndSaveTile
需要一段时间,因此我想使用线程池将该任务拆分为新线程。我试图使用Task.Factory.StartNew
来完成此任务。问题是我需要将这4个参数传递给线程,所以我必须创建一个可以转换为对象的类。
private class CropInfo
{
public CropInfo(Image image, int x, int y, int level)
{
Image = image;
X = x;
Y = y;
Level = level;
}
public Image Image { get; set; }
public int X { get; set; }
public int Y { get; set; }
public int Level { get; set; }
}
private static void SplitTilesRecursive(Image original, int level)
{
// ...
using (Image resized = ResizeImage(original, new Size(mapWidth, mapWidth)))
{
for (int x = 0; x < tilesOnSide; x++)
for (int y = 0; y < tilesOnSide; y++)
{
Task.Factory.StartNew(CropAndSaveTile, new CropInfo(resized, x, y, level));
}
}
// ...
}
private static void CropAndSaveTile(object o)
{
var info = (CropInfo) o;
// ...
}
这几乎可行。问题是new Bitmap(info.Image)
抛出ArgumentException
(参数无效)。我已经在不使用Task.Factory.StartNew
的情况下对此进行了测试,而是使用CropAndSaveTile(new CropInfo(resized, x, y, level));
直接调用该方法,并且工作正常。 StartNew
和线程之间发生了一些事情。这可能是SplitTilesRecursive
结束循环并导致resized
处理时导致的同步问题吗?如果没有,我如何正确地将多个参数传递给线程以用作线程池的一部分?
答案 0 :(得分:2)
为什么要创建课程?你可以这样做:
Task.Factory.StartNew(()=>CropandSaveTile(resized, y, y, level));
该语言将为您创建一个课程作为“封闭”。
答案 1 :(得分:2)
尝试在循环中使用x
和y
的本地副本:
for (int x = 0; x < tilesOnSide; x++)
for (int y = 0; y < tilesOnSide; y++)
{
int x1 = x;
int y1 = y;
Task.Factory.StartNew(() => CropAndSaveTile(resized, x1, y1, level));
}
这可以保证每个lambda都会看到一对独立的x
和y
值。