2009-02-06 5 views
3

У меня проблема с приложением Windows Forms с Bitmap.Save сбоем при сохранении в MemoryStream. Проблема, по-видимому, периодически возникает на одной машине (пока) и плохая новость на клиентском сайте. Я не могу отлаживать машину, но у меня есть трассировка стека, которая сузила проблему до одной строки кода.GDI + исключение, сохраняющее растровое изображение в MemoryStream

Вот сокращенный вариант моего кода:

byte[] ConvertPixelsToBytes() 
{ 
    // imagine a picture class that creates a 24 bbp image, and has 
    // a method to get an unmanaged pixel buffer. 
    // imagine it also has methods for getting the width, 
    // height, pitch 

    // I suppose this line could return a bad address, but 
    // I would have expected that the Bitmap constructor would have 
    // failed if it was 
    System.IntPtr pPixels = picture.GetPixelData(); 

    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(
      picture.width(), 
      picture.height(), 
      picture.pitch(), 
      System.Drawing.Imaging.PixelFormat.Format24bppRgb, 
      pPixels); 

    // This line doesn't actually free the memory, but it could be freed in a 
    // background thread 
    // (2) 
    picture.releasePixelData(pPixels); 

    System.IO.MemoryStream memStream = new System.IO.MemoryStream(); 
    try 
    { 
     // I don't see how this line could fail, but it does 
     // (3) 
     bmp.Save(memStream, System.Drawing.Imaging.ImageFormat.Bmp); 
     return memStream.ToArray(); 
    } 
    catch(System.Runtime.InteropServices.ExternalException e) 
    { 
     // e.Message is the very helpful " A generic error occurred in GDI+." 
    } 
    finally 
    { 
     memStream.Dispose(); 
    } 
    return new byte[0]; 
} 

Любая идея, что может быть происходит? Я почти уверен, что мой буфер пикселей прав, он всегда работает на наших dev/test машинах и на других сайтах клиентов.

Мои мысли о возможных причинах неудачи

а. Конструктор растрового изображения не копирует данные пикселя, но сохраняет ссылку на него, и сбой сохраняется, поскольку память освобождается. Я не нахожу, что документы MSDN очищаются по этому вопросу, но я предполагаю, что Bitmap копирует данные пикселей, а не предполагает, что он заблокирован.

b. Данные пикселя недействительны и приводят к отказу метода Save. Я сомневаюсь в этом, так как мои пиксельные данные составляют 24 бит на пиксель, поэтому, насколько я знаю, это не должно быть недопустимым.

c. В .NET Framework есть проблема.

Я был бы признателен за любые мысли по другим возможным причинам отказа, поэтому я могу добавить дополнительную информацию о проверке и регистрации в мое приложение, чтобы я мог отправить что-то в поле.

+0

Любое конкретное исключение? Или это один из тех poseky «Ошибка Gerneic GDI + произошла ошибка»? –

+0

Это один из тех исключений «Общий GDI +». –

ответ

5

The MSDN документов для этого Bitmap конструктора не оставляет никаких сомнений:

Примечание Вызывающие отвечают за распределение и освобождения блока памяти, заданного параметром scan0, однако, памяти должна не будет выпущен до тех пор, пока не будет выпущен соответствующий битмап.

+0

Спасибо. Это фактически не документировано в библиотеке MSDN для Visual Studio 2005 (в следующий раз я также проверю онлайн-документы). –

+0

У меня проблема, которая очень похожа на это, также используя bmp.Save (memStream, ...и т. д. Хотя кажется, что в документации упоминается то, что вы говорите, она, по-видимому, относится к потоку памяти, используемому в конструкторе bmp, - теперь это имеет смысл, но труднее принять, что поток памяти, который имеет растровое изображение, сохраненный в должен быть сохранен в актуальном состоянии - я писал в png, он только идет не так на производственной машине, и проблема прерывистая, только фиксируется, если пул приложений перерабатывается. Уже 10 лет работает без проблем. Но спасибо за информацию! – Cato

2

Вы пробовали двигаться

picture.releasePixelData(pPixels); 

в

finally 
    { 
     memStream.Dispose(); 
     picture.releasePixelData(pPixels); 
    } 

это определенно звучит как вопрос многопоточности (тем более, что вы заявляете, что releasePixelData может произойти на фоне потока). Проблемы с потоками - это всегда те, которые происходят только на одной машине, и она всегда находится на машине клиента (вероятно, из-за того, что у них только 256 мегабайт памяти или что-то нелепое, а сборщик мусора начинает пинать рано, или машина имеет четырехъядерный процессор и ваша машина для разработчиков является двухъядерной или что-то еще).

Смежные вопросы