Подморозка интерфейса?!
|
|
timurar77 | Дата: Пятница, 08.07.2022, 14:34 | Сообщение # 1 |
Рядовой
Группа: Пользователи
Сообщений: 8
Статус: Offline
| При множественных вычислениях замораживается интерфейс
Добавлено (08.07.2022, 14:36) --------------------------------------------- При запуске программы в которой выполняется множество вычислений замораживается интерфейс до окончания вычислений, даже прогресбар не двигается. Довольно не приятно и такую программу заказчику стыдно показывать. Если кто знает чем это можно вылечить.
После создания программы с многопоточностью, возникла неудобная аномалия.
Добавлено (07.07.2022, 13:30) --------------------------------------------- В одной из предыдущих тем "Многопоточность", я просил помощи в написании программы которая ее использует. Спасибо всем кто принимал участие в решении моей проблемы, в результате все прекрасно заработало. Однако При запуске программы где то через пол секунды интерфейс программы замерзает и отмерзает после решения внутреннего алгоритма. Есть подозрение, что это вызвано именно использованием многопоточности (а может и не ей). Нашел на другом форуме интересное обсуждение "http://www.prog.org.ru/index.php?topic=27922.0", похожей проблемы. Если кто знает в чем проблема, подскажите в каком направлении искать. Если это все же многопоточность подмораживает интерфейс, вот цикл который вызывает многопоточность. Здесь кусок программы который вызывает потоки, далее ожидается закрытие потоков, далее данные пишутся в файл, далее отрисовывается текущая позиция прогресбара.
Код While EOF(3)=0 'проверяем не достигнут ли конец файла
Erase mz Erase npot kzp=0 Erase mksi Erase mo
For i=0 To 119'Potoki moi=0 While Eof(3)=0 And moi<36 moi=moi+1 Get #3,,mz(i,moi)'bsim'чтение байта из файла в колличестве 36 Wend
npot(i)=i'массив номеров задействованных потоков If moi>0 Then kzp=i'номер последнего задействованного потока handles(i) = ThreadCreate(Cast(Any Ptr,@DShifr()),Cast(Any Ptr,npot(i))) EndIf Next 'ожидание завершения открытых потоков For i = 0 To kzp If handles(i) <> 0 Then ThreadWait(handles(i)) Next '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'запись в файл For i=0 To kzp For a=1 To mksi(i) Put #5,,mo(i,a)'запись блока данных в файл Next Next
ttPoz=LOC(3)'определение текущей позиции в файле в байтах tPoz= Int(ttPoz*100/dlf)'определяем текущую позицию в файле SendDlgItemMessage(hDlg,IDC_PGB1,PBM_SETPOS,tPoz,0)'прогрессбар обработки файла Wend
Добавлено (08.07.2022, 14:28) --------------------------------------------- Попробовал добавить мьютексы, стало работать медленнее и замерзает быстрее!?
Добавлено (08.07.2022, 14:29) --------------------------------------------- Значит проблема заморозки интерфейса не в многопоточности.
От администратора: по просьбе автора темы , удалил одну из тем , но сделал слияние сообщения в эту тему.
|
|
| |
zamabuvaraeu | Дата: Среда, 13.07.2022, 08:19 | Сообщение # 2 |
Подполковник
Группа: Друзья
Сообщений: 149
Статус: Offline
| Так вы же сами замораживаете GUI на функции ThreadWait. Все Wait‐функции возвращают управление только когда объект ожидания становится сигнальным. В случае потока — после того, как поток завершается. Результат: пока все ваши дополнительные потоки работают, ваше GUI будет заморожено.
Варианты. 1. Ваши потоки могут уведомлять GUI об окончании операции через функцию PostMessage. 2. Когда потоков больше количества ядер в системе, следует переходить на пул потоков. Пул потоков — это когда потоки создают заранее и ставят им в очередь задачи на исполнение. Вы можете либо сами создать пул потоков, либо использовать уже готовые функции QueueUserWorkItem (для ЦПУ‐задач) или BindIoCompletionCallback (для задач ввода‐вывода).Добавлено (13.07.2022, 08:43) --------------------------------------------- Как вообще работает GUI?
GUI основано на цикле выборки сообщений. У каждого потока есть очередь сообщений. В эту очередь система или вы сами помещаете сообщения. Например, сообщения для отрисовки окон, сообщения о щелчках мыши, нажатии и отпускании клавиатуры. Вам следует извлекать сообщения из очереди и обрабатывать их.
Упрощённый цикл выборки сообщений:
Do While GetMessage() ' Вызываем обработчик сообщений DispatchMessage() Loop
Чтобы функция GetMessage() извлекла сообщение из очереди, функция DispatchMessage() должна завершиться. Это не система вызывает вас когда есть сообщение в очереди, это вы сами должны извлекать из очереди сообщение и передавать их обработчику.
Ваш обработчик сообщений застыл на функции WaitThread. Следовательно, DispatchMessage() тоже застыло и не может перейти к GetMessage() чтобы извлечь сообщение из очереди. А раз сообщение из очереди не извлекается, то никакие GUI события не обрабатыватся, интерфейс не прорисовывается, окно не реагирует на клавиатуру, мышь и всё такое.
|
|
| |
timurar77 | Дата: Среда, 13.07.2022, 09:26 | Сообщение # 3 |
Рядовой
Группа: Пользователи
Сообщений: 8
Статус: Offline
| Может быть совет дельный. А как же быть со следующим: количество потоков за раз не более 120, после ожидания завершения потоков данные записываются в файл и потом вызываются команды отрисовки прогрессбара, все работает красиво но не более 1 секунды, потом отрисовав скажем половину прогрессбара (для файла размером 2 Мбит) программа как будто бы решает что ей ничего рисовать не нужно и начинает только вычислять без прорисовки прогрессбара до конца вычислений. Почему в начале все сообщения в своих очередях, а через секунду нет? Если обрабатывать файл скажем размером 800 кбит (это грубо 50 раз по 120 потоков, то есть полный цикл проходит в пределах 50 раз) то никаких проблем нет, вот это больше всего обескураживает.
Буду изучать и пробовать пул потоков?!Добавлено (13.07.2022, 10:12) --------------------------------------------- Вот обычная программа без потоков, которая тоже при определенных условиях подмораживается. Судоку. Sudoku (весь код не влазиет в форум)
при таких данных
нормально работает 6 секунд, затем интерфейс становиться с пометкой (Не отвечает) и размораживается после 17 секунд работы. Во время основного цикла вычислений отсылки сообщений интерфейсу тоже нет. В этом алгоритме вызова потоков нет. Добавлено (13.07.2022, 10:26) --------------------------------------------- раньше в алгоритме была визуализация решения с таким же эффектом замораживания, но не сразу, для увеличения скорости визуализацию убрал Добавлено (13.07.2022, 10:28) ---------------------------------------------
Цитата zamabuvaraeu ( ) Чтобы функция GetMessage() извлекла сообщение из очереди, функция DispatchMessage() должна завершиться. Это не система вызывает вас когда есть сообщение в очереди, это вы сами должны извлекать из очереди сообщение и передавать их обработчику. может в этом направлении покопать?Добавлено (13.07.2022, 10:31) ---------------------------------------------
Цитата zamabuvaraeu ( ) Do While GetMessage()' Вызываем обработчик сообщений DispatchMessage() Loop Попробую такой способ (потом напишу результат)Добавлено (13.07.2022, 11:47) ---------------------------------------------
Цитата zamabuvaraeu ( ) вы сами должны извлекать из очереди сообщение и передавать их обработчику Так, у меня ни какое сообщение из окна извлекать не надо. Код SendDlgItemMessage(hDlg,IDC_PGB1,PBM_SETPOS,tPoz,0)'прогрессбар обработки файла
У меня в окно отправляется сообщение. Казалось бы должно помочь такое Код SendDlgItemMessage(hDlg,IDC_PGB2,PBM_SETPOS,tPoz,0)'прогрессбар обработки файла ShowWindow(hDlg,SW_SHOW) UpdateWindow(hDlg)
Ни каких изменений, все так же. Может быть ждать когда сообщение будет доставлено? Цитата: "Возвращаемое значение Возвращаемое значение определяет результат обработки сообщения и зависит от отправленного сообщения. Замечания Функция SendDlgItemMessage не возвращает значения до тех пор, пока сообщение не будет обработано."Добавлено (14.07.2022, 10:25) --------------------------------------------- Может быть это особенность окон типа dialog, а с окнами типа window такого нет?! Кто нибудь вообще сталкивался с таким??
|
|
| |
zamabuvaraeu | Дата: Четверг, 14.07.2022, 10:33 | Сообщение # 4 |
Подполковник
Группа: Друзья
Сообщений: 149
Статус: Offline
| Пока у вас поток заблокирован на Wait — никакие ни ваши сообщения, ни системные извлечены из очереди не будут.
И это: >Так, у меня ни какое сообщение из окна извлекать не надо.
Надо. Иначе ваша программа не будет реагировать на сообщения мыши, клавиатуры п всего такого.
|
|
| |
timurar77 | Дата: Четверг, 14.07.2022, 17:16 | Сообщение # 5 |
Рядовой
Группа: Пользователи
Сообщений: 8
Статус: Offline
| Цитата zamabuvaraeu ( ) Пока у вас поток заблокирован на Wait поток на wait не заблокирован, так как файл пишется как положено (запись файла как раз идет после wait) все потоки отрабатываются за определенное время (небольшое) и завершаются, я же написал на примере что при обработке файла размером 2 Мбита как минимум 50 раз проходит полный цикл без заморозки и на примере другой программы без потоков, что заморозка возникает не из-за потоков. А конструкцию (на подобии) Do While GetMessage() DispatchMessage() Loop я уже пробовал, так программа вообще ничего не делает от слова совсем. хотелось бы уточнить, что заморозка интерфейса происходит не сразу, в первом примере через секунду, во втором примере через 6 секунд.Добавлено (14.07.2022, 18:31) --------------------------------------------- Вот пример простой программы можете проверить у себя Код #Include Once "windows.bi" #Include Once "win/commdlg.bi" #Include Once "win/commctrl.bi" #Include "zamorozka.bi"
Declare Function DlgProc(ByVal hWin As HWND, ByVal uMsg As UINT, ByVal wParam As WPARAM, ByVal lParam As LPARAM) As Integer hInstance=GetModuleHandle(NULL) DialogBoxParam(hInstance, Cast(ZString Ptr,IDD_DLG1), NULL, @DlgProc, NULL) ExitProcess(0) End Function DlgProc(ByVal hDlg As HWND,ByVal uMsg As UINT,ByVal wParam As WPARAM,ByVal lParam As LPARAM) As Integer Dim As Long id, Event, x, y Dim hBtn As HWND Dim rect As RECT Dim As LongInt dan, i Dim As Integer tPoz Dim As Double otv Dim buff As ZString*20
Select Case uMsg Case WM_INITDIALOG ' Case WM_CLOSE EndDialog(hDlg, 0) ' Case WM_COMMAND id=LoWord(wParam) Event=HiWord(wParam) Select Case id Case IDC_BTN2 GetDlgItemText(hDlg,IDC_EDT1,buff,260) dan=Val(buff) otv=0.5 For i=1 To dan otv=1+otv otv=1/otv tPoz= Int(i*100/dan)'определяем текущую позицию в процентах SendDlgItemMessage(hDlg,IDC_PGB1,PBM_SETPOS,tPoz,0) Next i buff=Str(otv) SetDlgItemText(hDlg,IDC_EDT2,buff) MessageBox(hDlg,"Готово","ХаХаХа",MB_ICONINFORMATION) SendDlgItemMessage(hDlg,IDC_PGB1,PBM_SETPOS,0,0) SetDlgItemText(hDlg,IDC_EDT2,"") Case IDC_BTN1 EndDialog(hDlg, 0) ' End Select Case WM_SIZE GetClientRect(hDlg,@rect) hBtn=GetDlgItem(hDlg,IDC_BTN1) x=rect.right-100 y=rect.bottom-35 MoveWindow(hBtn,x,y,97,31,TRUE) ' Case Else Return FALSE ' End Select Return TRUE
End Function
Вот сам проект zamorozka.rar Вот результаты работы с разными данными
Добавлено (14.07.2022, 18:35) --------------------------------------------- Программа выше написана для окна типа dialog Попробую эту же программу для окна типа window Добавлено (14.07.2022, 19:48) --------------------------------------------- Тот же результат с другим типом окна Код #Include once "windows.bi" #Include Once "win/commctrl.bi" #Include Once "win/commdlg.bi" #Include Once "win/shellapi.bi" #Include "zamorozka2.bi"
Function WndProc(ByVal hWin As HWND,ByVal uMsg As UINT,ByVal wParam As WPARAM,ByVal lParam As LPARAM) As Integer Dim As LongInt dan, i Dim As Integer tPoz Dim As Double otv Dim buff As ZString*20 Select Case uMsg Case WM_INITDIALOG hWnd=hWin ' Case WM_COMMAND Select Case HiWord(wParam) Case BN_CLICKED,1 Select Case LoWord(wParam) Case IDC_BTN1 GetDlgItemText(hWin,IDC_EDT1,buff,260) dan=Val(buff) otv=0.5 For i=1 To dan otv=1+otv otv=1/otv tPoz= Int(i*100/dan)'определяем текущую позицию в процентах SendDlgItemMessage(hWin,IDC_PGB1,PBM_SETPOS,tPoz,0) Next i buff=Str(otv) SetDlgItemText(hWin,IDC_EDT2,buff) MessageBox(hWin,"Готово","ХаХаХа",MB_ICONINFORMATION) SendDlgItemMessage(hWin,IDC_PGB1,PBM_SETPOS,0,0) SetDlgItemText(hWin,IDC_EDT2,"") Case IDM_FILE_EXIT SendMessage(hWin,WM_CLOSE,0,0) ' Case IDM_HELP_ABOUT ShellAbout(hWin,@AppName,@AboutMsg,NULL) ' End Select ' End Select ' Case WM_SIZE ' Case WM_CLOSE DestroyWindow(hWin) ' Case WM_DESTROY PostQuitMessage(NULL) ' Case Else Return DefWindowProc(hWin,uMsg,wParam,lParam) ' End Select Return 0
End Function
Function WinMain(ByVal hInst As HINSTANCE,ByVal hPrevInst As HINSTANCE,ByVal CmdLine As ZString ptr,ByVal CmdShow As Integer) As Integer Dim wc As WNDCLASSEX Dim msg As MSG
' Setup and register class for dialog wc.cbSize=SizeOf(WNDCLASSEX) wc.style=CS_HREDRAW or CS_VREDRAW wc.lpfnWndProc=@WndProc wc.cbClsExtra=0 wc.cbWndExtra=DLGWINDOWEXTRA wc.hInstance=hInst wc.hbrBackground=Cast(HBRUSH,COLOR_BTNFACE+1) wc.lpszMenuName=Cast(ZString Ptr,IDM_MENU) wc.lpszClassName=@ClassName wc.hIcon=LoadIcon(NULL,IDI_APPLICATION) wc.hIconSm=wc.hIcon wc.hCursor=LoadCursor(NULL,IDC_ARROW) RegisterClassEx(@wc) ' Create and show the dialog CreateDialogParam(hInstance,Cast(ZString Ptr,IDD_DIALOG),NULL,@WndProc,NULL) ShowWindow(hWnd,SW_SHOWNORMAL) UpdateWindow(hWnd) ' Message loop Do While GetMessage(@msg,NULL,0,0) TranslateMessage(@msg) DispatchMessage(@msg) Loop Return msg.wParam
End Function
' Program start hInstance=GetModuleHandle(NULL) CommandLine=GetCommandLine InitCommonControls WinMain(hInstance,NULL,CommandLine,SW_SHOWDEFAULT) ExitProcess(0)
End
вот сам проект zamorozka2.rar
Сообщение отредактировал timurar77 - Четверг, 14.07.2022, 17:16 |
|
| |
haav | Дата: Четверг, 14.07.2022, 21:21 | Сообщение # 6 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: Offline
| Я не пробовал оба кода , но первый отрабатывает без зависаний. Непонятно только, нафига отправлять в очередь такую кучу сообщений? В курсе , что вводя 900000 , в очередь попадет такое кол-во?
Все можно сделать примерно так:
Код For i=1 To dan otv=1+otv otv=1/otv tPoz= Int(i*100/dan)'определяем текущую позицию в процентах Next i SendDlgItemMessage(hDlg,IDC_PGB1,PBM_SETPOS,tPoz,0)
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
zamabuvaraeu | Дата: Пятница, 15.07.2022, 08:53 | Сообщение # 7 |
Подполковник
Группа: Друзья
Сообщений: 149
Статус: Offline
| >поток на wait не заблокирован
Неверно. Поток на любой Wait‐функции блокируется. Вы не сможете ожидать завершения без блокировки. Вы не можете ждать и одновременно продолжать работу. В этом вся суть ожидания.
|
|
| |
timurar77 | Дата: Пятница, 15.07.2022, 14:45 | Сообщение # 8 |
Рядовой
Группа: Пользователи
Сообщений: 8
Статус: Offline
| Цитата haav ( ) Я не пробовал оба кода , но первый отрабатывает без зависаний. Непонятно только, нафига отправлять в очередь такую кучу сообщений? В курсе , что вводя 900000 , в очередь попадет такое кол-во?Все можно сделать примерно так: Смысл использования прогрессбара в том что бы как раз и видеть что программа работает и что то вычисляет, а не зависла. Речь шла не о зависании программы как могло бы показаться, а о том что программа визуально выглядит как зависшая а на самом деле игнорировала интерфейс до конца своей работы. Прогрессбар был нужен именно для того что бы видеть что программа выполняет свою задачу наглядно а не в тихоря. В вашем примере прогрессбар вообще не нужен. Лучше такой код
Код For i=1 To 100 For a=1 To dan\100 otv=1+otv otv=1/otv Next a tPoz= Int(i)'îïðåäåëÿåì òåêóùóþ ïîçèöèþ â ïðîöåíòàõ SendDlgItemMessage(hDlg,IDC_PGB1,PBM_SETPOS,tPoz,0) Next i
но даже в этом случае
Цитата zamabuvaraeu ( ) на любой Wait‐функции блокируется не об этом речь а о том что это не на все время работы программы
Цитата timurar77 ( ) все потоки отрабатываются за определенное время (небольшое) и завершаются если бы как вы думаете Wait блокировала дальнейшую работу программы то файл бы не писался, а он пишется как положено Код 'ожидание завершения открытых потоков For i = 0 To kzp If handles(i) <> 0 Then ThreadWait(handles(i)) Next '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'запись в файл For i=0 To kzp For a=1 To mksi(i) Put #5,,mo(i,a)'запись блока данных в файл Next Next
и вообще я уже давно привел пример программ без потоков с заморозкой интерфейсаЦитата timurar77 ( ) Вот сам проект zamorozka.rarВот результаты работы с разными данными если нечем больше посоветовать, то не пишите об одном и том же и читайте внимательнее.Добавлено (15.07.2022, 14:54) --------------------------------------------- единственно весь этот спор помог мне осознать что можно немного ускорить программу. Я действительно слишком часто обращаюсь к прогрессбару в своей многопоточной программе, а это ресурсоемкий процесс. Постараюсь уменьшить количество обращений до минимального (конечно это не решит вопроса заморозки интерфейса, но немного ускорит программу) Добавлено (15.07.2022, 15:46) --------------------------------------------- ускорило на 1,3%
|
|
| |
haav | Дата: Пятница, 15.07.2022, 16:06 | Сообщение # 9 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: Offline
| Есть скажем 5 потоков , один из них выполняет операцию с gui. Пусть 4 из них что-то там обрабатывают в памяти. Надеюсь из разных потоков не ведется одновременное обращение к харду? Я так понимаю , потоки запускаются раньше цикла , который отправляет PBM_SETPOS? Так вот 5-й поток с GUI будет "стоять" или точнее вертеться на одном месте пока крутятся вложенные циклы:
Код For i=1 To 100 For a=1 To dan\100 otv=1+otv otv=1/otv Next a tPoz= Int(i)'îïðåäåëÿåì òåêóùóþ ïîçèöèþ â ïðîöåíòàõ SendDlgItemMessage(hDlg,IDC_PGB1,PBM_SETPOS,tPoz,0) Next i
Все сообщения , отправленные с помощью SendDlgItemMessage просто становятся в очередь и не ведется их извлечение , пока поток не выйдет из циклов и далее из оконной процедуры. Оконный интерфейс все это время не обновляется! А затем все эти сообщения снежным комом вылетят как из пушки. Я понимаю , что ожидается , но алгоритм в корне неверен с моей точки зрения. Что будет , если вложенные циклы уже отработают (5 поток c GUI освободится) , но другие потоки еще что-то обрабатывают? Или что будет если все потоки кроме 5 отработают , но последний еще вертится во вложенном цикле?
P.S. Все это конечно не имеет смысла , потому что нормально не задан вопрос. Покажи минимально возможный код с потоками , который имеет проблемы , о которых идет речь. Тогда увеличится вероятность подсказать что-то дельное. А так это пустая болтовня.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
timurar77 | Дата: Пятница, 15.07.2022, 18:39 | Сообщение # 10 |
Рядовой
Группа: Пользователи
Сообщений: 8
Статус: Offline
| вопрос в подморозке интерфейса, а не в не законченых потоках. Я уже привел программы без потока, обычные, в том числе и эта обычная Код For i=1 To 100 For a=1 To dan\100 otv=1+otv otv=1/otv Next a tPoz= Int(i)'îïðåäåëÿåì òåêóùóþ ïîçèöèþ â ïðîöåíòàõ SendDlgItemMessage(hDlg,IDC_PGB1,PBM_SETPOS,tPoz,0) Next i
Вот сам проект zamorozka.rar вот результат (в какой то момент у интерфейса появляется надпись (Не отвечает))
вот основной код Код #Include Once "windows.bi" #Include Once "win/commdlg.bi" #Include Once "win/commctrl.bi" #Include "zamorozka.bi"
Declare Function DlgProc(ByVal hWin As HWND, ByVal uMsg As UINT, ByVal wParam As WPARAM, ByVal lParam As LPARAM) As Integer hInstance=GetModuleHandle(NULL) DialogBoxParam(hInstance, Cast(ZString Ptr,IDD_DLG1), NULL, @DlgProc, NULL) ExitProcess(0) End Function DlgProc(ByVal hDlg As HWND,ByVal uMsg As UINT,ByVal wParam As WPARAM,ByVal lParam As LPARAM) As Integer Dim As Long id, Event, x, y Dim hBtn As HWND Dim rect As RECT Dim As LongInt dan, i Dim As Integer tPoz Dim As Double otv Dim buff As ZString*20
Select Case uMsg Case WM_INITDIALOG ' Case WM_CLOSE EndDialog(hDlg, 0) ' Case WM_COMMAND id=LoWord(wParam) Event=HiWord(wParam) Select Case id Case IDC_BTN2 GetDlgItemText(hDlg,IDC_EDT1,buff,260) dan=Val(buff) otv=0.5 For i=1 To dan otv=1+otv otv=1/otv tPoz= Int(i*100/dan)'определяем текущую позицию в процентах SendDlgItemMessage(hDlg,IDC_PGB1,PBM_SETPOS,tPoz,0) Next i buff=Str(otv) SetDlgItemText(hDlg,IDC_EDT2,buff) MessageBox(hDlg,"Готово","ХаХаХа",MB_ICONINFORMATION) SendDlgItemMessage(hDlg,IDC_PGB1,PBM_SETPOS,0,0) SetDlgItemText(hDlg,IDC_EDT2,"") Case IDC_BTN1 EndDialog(hDlg, 0) ' End Select Case WM_SIZE GetClientRect(hDlg,@rect) hBtn=GetDlgItem(hDlg,IDC_BTN1) x=rect.right-100 y=rect.bottom-35 MoveWindow(hBtn,x,y,97,31,TRUE) ' Case Else Return FALSE ' End Select Return TRUE
End Function
когда программа забывает про интерфейс и что то вычисляет, случай не единичный (последнюю программу написал для примера подморозки). Как только есть много вычислений сразу же интерфейс подмораживается (что не значит что программа зависла) (Забудьте про потоки я уже понял что заморозка интерфейса не из-за них)
|
|
| |
zamabuvaraeu | Дата: Пятница, 15.07.2022, 18:56 | Сообщение # 11 |
Подполковник
Группа: Друзья
Сообщений: 149
Статус: Offline
| DlgProc просто долго работает. Пока процессор обрабатывает функцию DlgProc, никакие сообщения из очереди извлечены не будут = зависание интерфейса. Вы не можете извлекать сообщения из очереди одновременно с работой DlgProc. Сообщение из очереди будут извлечено только после того DlgProc завершается.
|
|
| |
haav | Дата: Пятница, 15.07.2022, 19:40 | Сообщение # 12 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: Offline
| Цитата zamabuvaraeu ( ) Пока процессор обрабатывает функцию DlgProc, никакие сообщения из очереди извлечены не будут = зависание интерфейса.Вы не можете извлекать сообщения из очереди одновременно с работой DlgProc. Сообщение из очереди будут извлечено только после того DlgProc завершается. Так я ему тоже самое и объяснял. timurar77 наверное думает , что если послал сообщение с помощью SendDlgItemMessage из оконной процедуры , то интерфейс сразу обновится. Нет , это не так! Системе надо вернуть управление , а для этого надо чтобы оконная процедура завершилась. Только после этого система начнет извлекать нужные сообщения и обрабатывать их. А до тех пор , все сообщения (почти миллиард судя по скриншоту) она помещает в очередь и ждет когда ей (системе) передадут управление.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
zamabuvaraeu | Дата: Пятница, 15.07.2022, 20:39 | Сообщение # 13 |
Подполковник
Группа: Друзья
Сообщений: 149
Статус: Offline
| Миллиард — это 1 000 000 000. Умножаем на 4 или даже 8, получаем 4000000000. 4 или 8 гигабайт. Сделаем фантастическое допущение, что все эти четыре гигабайта каким‐то образом влезут в оперативную память.
Однако ёмкость очереди сообщений Windows не настолько большая, и на десяти тысячах сообщений их уже откинет.
|
|
| |
timurar77 | Дата: Пятница, 15.07.2022, 21:17 | Сообщение # 14 |
Рядовой
Группа: Пользователи
Сообщений: 8
Статус: Offline
| Интересно, значит нужно дождаться завершения DlgProc, что бы? что ... Вот таже программа но с другими параметрами (работает примерно 3 секунды) и никаких проблем.
вот гиф-видео обоих случаев первый случай когда интерфейс подмораживается немного в конце
второй случай когда никаких проблем нет в том числе и с DlgProc
причина звучит убедительно но не логично (если виновата DlgProc почему прогрессбар вообще отрисовывается)
Добавлено (15.07.2022, 21:29) --------------------------------------------- (Сказали бы хотя бы что ветка "Case IDC_BTN2" должна завершиться и то больше было бы похоже на правду)
Добавлено (15.07.2022, 22:02) --------------------------------------------- "Миллиард — это 1 000 000 000. Умножаем на 4 или даже 8, получаем 4000000000. 4 или 8 гигабайт. Сделаем фантастическое допущение, что все эти четыре гигабайта каким‐то образом влезут в оперативную память."
(память вообще не дергается, ЦП (одно из ядер) грузиться на 13% и нагрузка на диск, какие данные??? там всего три цифры)
Сообщение отредактировал timurar77 - Пятница, 15.07.2022, 22:06 |
|
| |
haav | Дата: Суббота, 16.07.2022, 06:46 | Сообщение # 15 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: Offline
| Загрузил винду и попробовал. Походу я не прав. Система судя по всему такие сообщения как PBM_SETPOS все таки внутри обрабатывает и даже обновляет интерфейс. Видно , что при больших нагрузках (отправке сообщений сотнями миллионов) все плющит , но она пытается и даже подвешивая программу все таки через какое-то время доходит до конца. Полагаться на такой алгоритм работы я бы точно не стал. Это может работать , а может и все встать в любой момент. Я бы обработку визуальной части прогрессбара поместил бы в таймер. Больше мне сказать нечего.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
|