使用带有任务并行库的Graphics.DrawImage发出问题/图像损坏?

时间:2014-03-02 23:11:20

标签: c# graphics task-parallel-library

我有一些代码可以获取上传的图像,将其大小调整为5种不同的大小,然后将这些代码上传到另一个存储库。我正在尝试使用TPL并行执行5个图像大小调整操作。

Upfront我会提到resizing函数是一个静态方法,但它不使用任何静态资源(所以多个并行调用不应该相互踩,从我所知道的)。 非常相关的是,这是在ASP.NET的上下文中,它有一些不同的线程问题。

当我运行以下代码时,我总是从其中一个调用中得到一个“无效参数”错误,尽管哪个调用有所不同:

tasks = new Task<Uri>[]
{
    Task.Run<Uri>(() => Upload(intId, ProfilePhotoSize.FiveHundredFixedWidth, photoStream, mediaType, minWidth)),
    Task.Run<Uri>(() => Upload(intId, ProfilePhotoSize.Square220, photoStream, mediaType, minWidth)),
    Task.Run<Uri>(() => Upload(intId, ProfilePhotoSize.Square140, photoStream, mediaType, minWidth)),
    Task.Run<Uri>(() => Upload(intId, ProfilePhotoSize.Square80, photoStream, mediaType, minWidth)),
    Task.Run<Uri>(() => Upload(intId, ProfilePhotoSize.Square50, photoStream, mediaType, minWidth))
};

await Task.WhenAll(tasks)

如果我查看创建的图像,有些图像会正常,有些图像会明显损坏 - 这不仅适用于“错误”图像。

然而,同步执行这五个操作会产生五个好的图像:

Upload(intId, ProfilePhotoSize.FiveHundredFixedWidth, photoStream, mediaType, minWidth);
Upload(intId, ProfilePhotoSize.Square220, photoStream, mediaType, minWidth);
Upload(intId, ProfilePhotoSize.Square140, photoStream, mediaType, minWidth);
Upload(intId, ProfilePhotoSize.Square80, photoStream, mediaType, minWidth);
Upload(intId, ProfilePhotoSize.Square50, photoStream, mediaType, minWidth);

这些操作是否存在已知问题,或者我可能做了其他可能造成这种情况的狡猾问题?

这是图像大小调整功能:

private static Stream Resize(Stream image, ResizeParameters parameters, ImageUtility.ResizeType type)
{
  Image image1 = (Image) new Bitmap(image);
  Image image2 = (Image) null;
  Image image3 = (Image) null;
  Graphics graphics = (Graphics) null;
  MemoryStream memoryStream = new MemoryStream();
  try
  {
    parameters = ImageUtility.CalculateSize(image1, parameters, type);
    if (!parameters.DoNothing)
    {
      image2 = (Image) new Bitmap(parameters.Width, parameters.Height);
      switch (type)
      {
        case ImageUtility.ResizeType.FixedWidth:
          graphics = Graphics.FromImage(image2);
          graphics.SmoothingMode = SmoothingMode.AntiAlias;
          graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
          graphics.FillRectangle(Brushes.White, 0, 0, image1.Width, image1.Height);
          graphics.DrawImage(image1, 0, 0, parameters.Width, parameters.Height);
          graphics.Dispose();
          break;
        case ImageUtility.ResizeType.PaddingSquare:
          image3 = (Image) new Bitmap(parameters.SelectedWidth, parameters.SelectedHeight);
          graphics = Graphics.FromImage(image3);
          graphics.SmoothingMode = SmoothingMode.AntiAlias;
          graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
          graphics.FillRectangle(Brushes.White, 0, 0, parameters.SelectedWidth, parameters.SelectedHeight);
          graphics.DrawImage(image1, parameters.X, parameters.Y, image1.Width, image1.Height);
          graphics = Graphics.FromImage(image2);
          graphics.DrawImage(image3, 0, 0, parameters.Width, parameters.Height);
          graphics.Dispose();
          break;
        case ImageUtility.ResizeType.CropSquare:
          image3 = (Image) new Bitmap(parameters.SelectedWidth, parameters.SelectedHeight);
          graphics = Graphics.FromImage(image3);
          graphics.SmoothingMode = SmoothingMode.AntiAlias;
          graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
          graphics.FillRectangle(Brushes.White, 0, 0, parameters.SelectedWidth, parameters.SelectedHeight);
          graphics.DrawImage(image1, new Rectangle(0, 0, parameters.SelectedWidth, parameters.SelectedHeight), parameters.X, parameters.Y, image3.Width, image3.Height, GraphicsUnit.Pixel);
          graphics = Graphics.FromImage(image2);
          graphics.DrawImage(image3, 0, 0, parameters.Width, parameters.Height);
          graphics.Dispose();
          break;
      }
      EncoderParameter encoderParameter = new EncoderParameter(Encoder.Quality, 90L);
      EncoderParameters encoderParams = new EncoderParameters(1);
      encoderParams.Param[0] = encoderParameter;
      image2.Save((Stream) memoryStream, ImageUtility.GetEncoder(parameters.Format), encoderParams);
    }
    else
    {
      image.Seek(0L, SeekOrigin.Begin);
      image.CopyTo((Stream) memoryStream);
    }
    memoryStream.Seek(0L, SeekOrigin.Begin);
    return (Stream) memoryStream;
  }
  finally
  {
    image1.Dispose();
    if (image2 != null)
      image2.Dispose();
    if (image3 != null)
      image3.Dispose();
    if (graphics != null)
      graphics.Dispose();
  }
}

0 个答案:

没有答案