Странная проблема. Может быть, кто-то может дать некоторое представление.
Сценарий 1 . У меня есть TBitmap в памяти, который записывается в то время, когда выполняются сложные вычисления для расчета цвета каждого пикселя. Время от времени (обычно после каждой горизонтальной линии, когда растровое изображение заполняется) TBitmap рисуется на изображении в форме (image1.Canvas.Draw (0, 0, TBitmap). В большинстве случаев это работает нормально, но я заметил, что если для каждой строки растрового изображения имеется много медленных сложных вызовов (скажем, для расчета более 30 секунд или минуты), то в главной форме появляется кратковременное «мерцание», которое каким-то образом стирает растровое изображение, поэтому вызов image.draw только отрисовывает последняя вычисленная строка и первые y-строки не отображаются в растровом изображении. Я справился с этим, заблокировав растровое изображение перед вычислениями.
Сценарий 2. Это главная неприятность. Я пишу в TMemoryStream, а не в растровое изображение. Та же сделка Расчеты выполняются для вычисления каждого значения пикселя, а затем каждое значение пикселя записывается в TMemoryStream с помощью memstream.Write (bytevalue, 1) во время процесса. В конце всех вычислений я сохраняю поток в растровое изображение с помощью memstream.SaveToFile ('what.bmp'), а затем освобождаю поток с помощью memstream.Free. Если расчет выполняется быстро, то поток сохраняется независимо от размера (я делаю тесты с размерами 10000x10000).
Я даже могу сказать, что полученный файл будет поврежден, так как главное окно / форма приложения слегка мигает, как будто его перекрашивают. Когда это происходит, все дескрипторы битовых карт и TMemoryStream уничтожаются / обновляются, поэтому существующие данные повреждены.
Есть идеи? Это действительно отстой. Особенно, когда создание каждого отдельного изображения может занять час, только чтобы обнаружить, что когда оно заканчивается, что-то на заднем плане произошло и повредило растровое изображение или TMemoryStream.
Можно ли как-нибудь заблокировать дескриптор TMemoryStream, как я могу с помощью растрового изображения? Это может помочь. Или какое-то объявление Delphi: «Не связывайтесь с моими объектами, даже если кажется, что приложение занимает слишком много времени»
Или кто-нибудь знает внутреннюю причину в Delphi, которая вызывает это.
TMemoryStream создается внутри процедуры, которая выполняет все вычисления, так же как и локальный объект. С проблемой растрового изображения растровое изображение было глобальной переменной вне процедуры, и это произошло, поэтому я не думаю, что это является причиной.
Это также под Windows 7, но я заметил исходную проблему растрового изображения под Vista.
Обновление 1:
Извините, что не использовал комментарии, но есть ограничение на размер текста ...
В ответ Реми (и всем, кто читает это) ...
Однопоточная. Для потока памяти он работает нормально для разрешения 5000x5000, если вычисления быстрые, но не работает, если вычисления медленные.
В качестве базовой структуры код выглядит так:
SetupMemorystream;
for y:=0 to height do
for x:=0 to width do
DoCalcs;
SetByteValue;
end;
end;
SaveStream;
Если DoCalcs относительно быстр, то все идет по плану. Если он медленный, я получаю повреждение TMemoryStream, и результирующий растр, в котором сохранен поток, поврежден.
Это было идентично использованию TBitmap в памяти, пока я не обнаружил, что могу заблокировать растровое изображение, которое останавливает Delphi и / или Windows, перераспределяя ему новый дескриптор «когда он хочет», который портит данные внутри растрового изображения.
Это слишком большое совпадение, чтобы не думать, что та же проблема не происходит с TMemoryStream и его дескриптором.
Обновление 2:
Еще одна полезная информация.
Когда TMemoryStream сохраняет OK, результирующий файл (для растрового изображения 5000x5000) имеет размер 75 000 054 байта.
Когда сохраненный поток поврежден, это кажется случайным значением (размера от момента, когда дескриптор был поврежден, до сохранения потока). Размеры примеров составляли 22 МБ и 9 МБ.
Когда я смотрю на получившиеся файлы, это шестнадцатеричный редактор, который показывает, что начало файлов правильно с кусками заголовка, но хвостовые концы как-то усекаются.
Это так странно. В любом случае, я могу абсолютно точно очистить TMemoryStream после вызова SaveToFile и перед его освобождением?