首页 > 解决方案 > 使用 System.Drawing 时发生崩溃、OutOfMemoryException、一般错误

问题描述

我在 C# 中运行一个 cron 作业,该作业需要 200,000 张图像并转换为 1 位图像。在运行此作业期间,有时process crashes(即使我有全局尝试捕获),有时对于某些图像(不是全部)它会抛出OutOfMemoryException,有时对于它会抛出的某些图像A generic error occurred in GDI

        int pageSize = 1000;
        for (int pageNumber = 0; pageNumber < 200; pageNumber++)
        {
            var imageUrls = allIMageUrls.Skip(pageSize * pageNumber).Take(pageSize).ToList();
            var counter = 0;
            var total = imageUrls.Count;
            Logger.Log($"Page Number : {pageNumber}");
            var failedImageUrls = new System.Collections.Concurrent.ConcurrentBag<string>();
            Parallel.ForEach(imageUrls, imageUrl =>
            {
                try
                {
                    Interlocked.Increment(ref counter);
                    var image = _httpService.DownloadImage(imageUrl);
                    if (image != null && image.Length > 0)
                    {
                        var oneBitImage = ConvertToOnebitFaxGroup4(contract);
                        _httpService.UploadImage(image, oneBitImage);
                        oneBitImage = null;
                        image  = null;
                    }
                }
                catch (Exception ex)
                {
                    failedImageUrls.Add(imageUrl);                        
                    Logger.Log(ex);
                }
            });

这是一次性的过程。我添加了分页,以便当它崩溃时我可以从该页面重新启动,而不是从头开始。

 public static class ImageProcessor
 {

    static ImageCodecInfo _codecInfo;
    static EncoderParameters _encoderParameters;

    static ImageProcessor()
    {
        foreach (var codec in ImageCodecInfo.GetImageEncoders())
        {
            if (codec.MimeType == "image/tiff")
            {
                _codecInfo = codec;
                break;
            }
        }
        _encoderParameters = new EncoderParameters(2);
        _encoderParameters.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionCCITT4);
        _encoderParameters.Param[1] = new EncoderParameter(Encoder.ColorDepth, (long)1);
    }

    public static byte[] ConvertToOnebitFaxGroup4(byte[] bytes)
    {
        using (var memoryStream = new MemoryStream(bytes))
        {
            var image = Image.FromStream(memoryStream);
            var pData = Marshal.AllocHGlobal(bytes.Length);
            Marshal.Copy(bytes, 0, pData, bytes.Length);
            var bytesPerLine = (image.Width + 31) / 32 * 4; 
            var img = new Bitmap(image.Width, image.Height, bytesPerLine, PixelFormat.Format1bppIndexed, pData);
            using (var ms = new MemoryStream())
            {
                image.Save(ms, _codecInfo, _encoderParameters);
                img.Dispose();
                Marshal.FreeHGlobal(pData);
                return ms.ToArray();
            }
        }
    }

更新:

    public static byte[] ConvertToOnebitFaxGroup4(byte[] bytes)
    {
        using (var memoryStream = new MemoryStream(bytes))
        {
            using (var image = Image.FromStream(memoryStream))
            {
                var pData = Marshal.AllocHGlobal(bytes.Length);
                Marshal.Copy(bytes, 0, pData, bytes.Length);
                var bytesPerLine = (image.Width + 31) / 32 * 4;
                using (var img = new Bitmap(image.Width, image.Height, bytesPerLine, PixelFormat.Format1bppIndexed, pData))
                {
                    using (var ms = new MemoryStream())
                    {
                        img.Save(ms, _codecInfo, _encoderParameters);
                        Marshal.FreeHGlobal(pData);
                        return ms.ToArray();
                    }
                }
            }
        }
    }

更新2

    public static byte[] ConvertToOnebitFaxGroup4(byte[] bytes)
    {
        using (var memoryStream = new MemoryStream(bytes))
        {
            using (var image = Image.FromStream(memoryStream))
            {
                using (var ms = new MemoryStream())
                {
                    image.Save(ms, _codecInfo, _encoderParameters);
                    return ms.ToArray();
                }
            }
        }
    }

标签: c#.netimage-processinggdi+.net-4.6.1

解决方案


推荐阅读