Перезапись оконной процедуры приводит к сбоям без ошибок, когда создается слишком много экземпляров. ⇐ Python
Перезапись оконной процедуры приводит к сбоям без ошибок, когда создается слишком много экземпляров.
Я создаю приложение, которое использует SDL/Pygame для отображения графики. Я перезаписал оконную процедуру на случай изменения размера для запуска функции и сделал работу приложения более плавной (см. этот ответ).
Однако я заметил, что при достижении определенного количества экземпляров класса происходит сбой приложения без каких-либо ошибок в журналах. Я проверил журналы Windows, но ничего не нашел. Я обнаружил, что виновником является перезапись оконной процедуры.
Ниже вы найдете симуляцию проблемы:
[*]Функция windows_resize_procedure (на основе этого ответа запускает App.resize и App.draw, когда пользователь изменяет размер окна [*][Element() for _ in range(1000)] создает искусственно большое количество экземпляров Element. В моей реальной программе их всего около 50, но я считаю их «большими» (больше атрибутов и методов). 1000 достаточно, чтобы программа на моем компьютере аварийно завершилась через несколько секунд, но вы можете увеличить это число в зависимости от вашего. импортировать pygame,sys,платформу def windows_resize_procedure(hwnd,draw_func,resize_func,screen): пытаться: импорт типов из ctypes импортировать WinTypes user32 = ctypes.windll.user32 WNDPROC = ctypes.WINFUNCTYPE( ctypes.c_long, wintypes.HWND, ctypes.c_uint, ctypes.POINTER(wintypes.WPARAM), ctypes.POINTER(wintypes.LPARAM)) WM_SIZE = 0x0005 РДВ_ИНВАЛИДАТЭ = 0x0001 РДВ_ERASE = 0x0004 GWL_WNDPROC = -4 old_window_proc = user32.GetWindowLongPtrA( user32.GetForegroundWindow(), GWL_WNDPROC ) def new_window_proc(hwnd, msg, wparam, lparam): если сообщение == WM_SIZE: resize_func(screen.get_size()) draw_func() user32.RedrawWindow(hwnd, Нет, Нет, RDW_INVALIDATE | RDW_ERASE) вернуть user32.CallWindowProcA (old_window_proc, hwnd, msg, wparam, lparam) new_window_proc_cb = WNDPROC(new_window_proc) user32.SetWindowLongPtrA( user32.GetForegroundWindow(), GWL_WNDPROC, ctypes.cast(new_window_proc_cb, ctypes.POINTER(ctypes.c_long)) ) кроме исключения как e: распечатать(е) Элемент класса: защита __init__(сам): self.foo = 'фу' классное приложение: защита __init__(сам): pygame.init() self.screen = pygame.display.set_mode((200,200),pygame.RESIZABLE ) self.clock = pygame.time.Clock() self.hwnd = pygame.display.get_wm_info()['окно'] # Комментирование двух следующих строк "исправляет" проблему # Это означает, что если не перезаписывать оконную процедуру, она работает хорошо если платформа.система() == 'Windows': windows_resize_procedure(self.hwnd,self.draw,self.resize,self.screen) self.elements = [] входные данные (сам): для события в pygame.event.get(): если event.type == pygame.QUIT: pygame.quit() sys.exit() # Имитация большого количества экземпляров [Элемент() для _ в диапазоне (1000)] def resize(self,size): print(изменение размера до {size}') защита ничья (сам): self.screen.fill('белый') защита запуска (сам): пока правда: self.inputs() pygame.display.update() сам.часы.тик() если __name__ == "__main__": приложение = Приложение() приложение.run()
Я создаю приложение, которое использует SDL/Pygame для отображения графики. Я перезаписал оконную процедуру на случай изменения размера для запуска функции и сделал работу приложения более плавной (см. этот ответ).
Однако я заметил, что при достижении определенного количества экземпляров класса происходит сбой приложения без каких-либо ошибок в журналах. Я проверил журналы Windows, но ничего не нашел. Я обнаружил, что виновником является перезапись оконной процедуры.
Ниже вы найдете симуляцию проблемы:
[*]Функция windows_resize_procedure (на основе этого ответа запускает App.resize и App.draw, когда пользователь изменяет размер окна [*][Element() for _ in range(1000)] создает искусственно большое количество экземпляров Element. В моей реальной программе их всего около 50, но я считаю их «большими» (больше атрибутов и методов). 1000 достаточно, чтобы программа на моем компьютере аварийно завершилась через несколько секунд, но вы можете увеличить это число в зависимости от вашего. импортировать pygame,sys,платформу def windows_resize_procedure(hwnd,draw_func,resize_func,screen): пытаться: импорт типов из ctypes импортировать WinTypes user32 = ctypes.windll.user32 WNDPROC = ctypes.WINFUNCTYPE( ctypes.c_long, wintypes.HWND, ctypes.c_uint, ctypes.POINTER(wintypes.WPARAM), ctypes.POINTER(wintypes.LPARAM)) WM_SIZE = 0x0005 РДВ_ИНВАЛИДАТЭ = 0x0001 РДВ_ERASE = 0x0004 GWL_WNDPROC = -4 old_window_proc = user32.GetWindowLongPtrA( user32.GetForegroundWindow(), GWL_WNDPROC ) def new_window_proc(hwnd, msg, wparam, lparam): если сообщение == WM_SIZE: resize_func(screen.get_size()) draw_func() user32.RedrawWindow(hwnd, Нет, Нет, RDW_INVALIDATE | RDW_ERASE) вернуть user32.CallWindowProcA (old_window_proc, hwnd, msg, wparam, lparam) new_window_proc_cb = WNDPROC(new_window_proc) user32.SetWindowLongPtrA( user32.GetForegroundWindow(), GWL_WNDPROC, ctypes.cast(new_window_proc_cb, ctypes.POINTER(ctypes.c_long)) ) кроме исключения как e: распечатать(е) Элемент класса: защита __init__(сам): self.foo = 'фу' классное приложение: защита __init__(сам): pygame.init() self.screen = pygame.display.set_mode((200,200),pygame.RESIZABLE ) self.clock = pygame.time.Clock() self.hwnd = pygame.display.get_wm_info()['окно'] # Комментирование двух следующих строк "исправляет" проблему # Это означает, что если не перезаписывать оконную процедуру, она работает хорошо если платформа.система() == 'Windows': windows_resize_procedure(self.hwnd,self.draw,self.resize,self.screen) self.elements = [] входные данные (сам): для события в pygame.event.get(): если event.type == pygame.QUIT: pygame.quit() sys.exit() # Имитация большого количества экземпляров [Элемент() для _ в диапазоне (1000)] def resize(self,size): print(изменение размера до {size}') защита ничья (сам): self.screen.fill('белый') защита запуска (сам): пока правда: self.inputs() pygame.display.update() сам.часы.тик() если __name__ == "__main__": приложение = Приложение() приложение.run()
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
OpenGL ES, слишком раннее заполнение VBO и IBO приводит к отсутствию буферов?
Гость » » в форуме C++ - 0 Ответы
- 5 Просмотры
-
Последнее сообщение Гость
-
-
-
OpenGL ES, слишком раннее заполнение VBO и IBO приводит к отсутствию буферов?
Гость » » в форуме C++ - 0 Ответы
- 5 Просмотры
-
Последнее сообщение Гость
-