System.ComponentModel.Win32Exception: операция успешно завершена - PullRequest
24 голосов
/ 31 июля 2009

Иногда я получаю это исключение при длительном запуске приложения Windows Forms:

System.ComponentModel.Win32Exception: The operation completed successfully
   at System.Drawing.BufferedGraphicsContext.CreateCompatibleDIB(IntPtr hdc, IntPtr hpal, Int32 ulWidth, Int32 ulHeight, IntPtr& ppvBits)
   at System.Drawing.BufferedGraphicsContext.CreateBuffer(IntPtr src, Int32 offsetX, Int32 offsetY, Int32 width, Int32 height)
   at System.Drawing.BufferedGraphicsContext.AllocBuffer(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle)
   at System.Drawing.BufferedGraphicsContext.AllocBufferInTempManager(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle)
   at System.Drawing.BufferedGraphicsContext.Allocate(IntPtr targetDC, Rectangle targetRectangle)
   at System.Windows.Forms.Control.WmPaint(Message& m)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.DataGridView.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Что может быть причиной этого?

Ответы [ 8 ]

21 голосов
/ 10 января 2011

Чтобы подвести итог, написанная мной пользовательская сетка, основанная на DataGridView .Net, использует собственный код для рисования ячеек. Строки в моей сетке могут занимать несколько визуальных страниц. (Это было деловое требование)

Проблема заключалась в том, что .Net предварительно выделяет буфер памяти для элементов управления с включенным DoubleBuffering. Для сеток DataGridView буфер должен быть достаточно большим, чтобы вместить возможные большие строки в сетке. В крайних случаях строка может занимать до 32000 пикселей (из-за ограничения .net). Ширина сетки в проекте обычно составляет от 500 до 800 пикселей. Таким образом, результирующий буфер может быть (32bpp * 800 * 32000 = ~ 100 МБ)

Короче говоря, система не могла создавать совместимые графические объекты, потому что иногда она не могла зарезервировать буфер, достаточно большой для размещения требуемых данных.

Чтобы исправить это, мне пришлось ввести ряд оптимизаций:

  • ограниченная максимальная высота строки, разрешенная в моей пользовательской сетке, до 1500 пикселей
  • обновлен код перераспределения буфера, чтобы он выполнялся только тогда, когда новый размер буфера больше существующего
  • гарантирует, что буферы не перераспределяются при каждой привязке данных и предварительно распределяются до разумного размера.
  • проверил весь код и убедился, что неуправляемые ресурсы правильно расположены, когда они не используются, как рекомендовано здесь: http://nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html
13 голосов
/ 21 июня 2011

Windows имеет жесткое ограничение 10000 дескрипторов на процесс. Довольно бесполезное исключение «Операция успешно завершена» может указывать на достижение этого предела.

Если это произошло из-за утечки ресурсов в вашем коде, то вам повезло, поскольку у вас по крайней мере есть возможность исправить свой код.

К сожалению, вы почти ничего не можете сделать с дескрипторами, созданными внутри WinForms. Например, плодотворное создание дескрипторов шрифтов с помощью элемента управления TreeView затрудняет использование в сценарии, когда очень большое дерево должно быть представлено в пользовательском интерфейсе.

Некоторые полезные ссылки:

http://support.microsoft.com/kb/327699 http://nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html

3 голосов
/ 13 июня 2012

У меня была такая же проблема в VB.NET. Причина этого была странной:

В Австрии наши системы Windows обычно имеют запятую и a. как тысячи сепаратор. Если это искажено (что является стандартным в США, я думаю), Windows выдаст эту ошибку. Изменение его в Австрии должно быть решено ...

Удачи!

3 голосов
/ 07 декабря 2011

У меня когда-то было похожее исключение при создании огромного PictureBox. Кажется, я не смог выделить достаточно большую графику. На самом деле я рисовал какую-то карту для простой игры, и у меня была функция масштабирования, которая в основном создавала больший буфер, а затем я перерисовывал всю графику в большем масштабе. Воспроизведение с этой функцией увеличения в течение длительного времени или на достаточно глубоком уровне вызвало это исключение. Возможно, вы создаете много графики и не утилизируете ее, или просто графика достаточно велика, чтобы ее нельзя было выделить.

2 голосов
/ 08 декабря 2010

Это вызвано в крайних случаях не утилизации изображений. Вы должны использовать IDisposable при загрузке растровых изображений, чтобы преодолеть это;

using(Bitmap b = Bitmap.FromFile("myfile.jpg"))
{
   //Do whatever
}
2 голосов
/ 31 июля 2009

Найдено это , которое может помочь - похоже, проблема утилизации графики или элемента управления

1 голос
/ 06 августа 2009

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

0 голосов
/ 21 декабря 2012

Кроме того, утечки памяти могут вызвать исключение. Например, приложение с 2-3 веб-браузерами может занять более 1 ГБ за несколько минут из-за одной из ошибок Internet Explorer, таких как this .

...