Сбои, OutOfMemoryException, общая ошибка при использовании System.Drawing - PullRequest
0 голосов
/ 13 сентября 2018

Я выполняю задание cron в C #, которое принимает 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();
                }
            }
        }
    }
...