FreeBasic
Главная
Вход
Регистрация
Пятница, 27.12.2024, 01:18Приветствую Вас Гость | RSS
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 2
  • 1
  • 2
  • »
Подморозка интерфейса?!
timurar77Дата: Пятница, 08.07.2022, 14:34 | Сообщение # 1
Рядовой
Группа: Пользователи
Сообщений: 8
Репутация: 0
Статус: 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
Репутация: 5
Статус: 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
Репутация: 0
Статус: 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
Репутация: 5
Статус: Offline
Пока у вас поток заблокирован на Wait — никакие ни ваши сообщения, ни системные извлечены из очереди не будут.

И это:
>Так, у меня ни какое сообщение из окна извлекать не надо.

Надо. Иначе ваша программа не будет реагировать на сообщения мыши, клавиатуры п всего такого.
 
timurar77Дата: Четверг, 14.07.2022, 17:16 | Сообщение # 5
Рядовой
Группа: Пользователи
Сообщений: 8
Репутация: 0
Статус: 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
Репутация: 50
Статус: 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
Репутация: 5
Статус: Offline
>поток на wait не заблокирован

Неверно.
Поток на любой Wait‐функции блокируется. Вы не сможете ожидать завершения без блокировки. Вы не можете ждать и одновременно продолжать работу. В этом вся суть ожидания.
 
timurar77Дата: Пятница, 15.07.2022, 14:45 | Сообщение # 8
Рядовой
Группа: Пользователи
Сообщений: 8
Репутация: 0
Статус: 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
Репутация: 50
Статус: 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
Репутация: 0
Статус: 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
Репутация: 5
Статус: Offline
DlgProc просто долго работает.
Пока процессор обрабатывает функцию DlgProc, никакие сообщения из очереди извлечены не будут = зависание интерфейса.
Вы не можете извлекать сообщения из очереди одновременно с работой DlgProc. Сообщение из очереди будут извлечено только после того DlgProc завершается.
 
haavДата: Пятница, 15.07.2022, 19:40 | Сообщение # 12
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Репутация: 50
Статус: Offline
Цитата zamabuvaraeu ()
Пока процессор обрабатывает функцию DlgProc, никакие сообщения из очереди извлечены не будут = зависание интерфейса.Вы не можете извлекать сообщения из очереди одновременно с работой DlgProc. Сообщение из очереди будут извлечено только после того DlgProc завершается.

Так я ему тоже самое и объяснял.
timurar77 наверное думает , что если послал сообщение с помощью SendDlgItemMessage из оконной процедуры , то интерфейс сразу обновится. Нет , это не так! Системе надо вернуть управление , а для этого надо чтобы оконная процедура завершилась. Только после этого система начнет извлекать нужные сообщения и обрабатывать их. А до тех пор , все сообщения (почти миллиард судя по скриншоту) она помещает в очередь и ждет когда ей (системе) передадут управление.


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
zamabuvaraeuДата: Пятница, 15.07.2022, 20:39 | Сообщение # 13
Подполковник
Группа: Друзья
Сообщений: 149
Репутация: 5
Статус: Offline
Миллиард — это 1 000 000 000. Умножаем на 4 или даже 8, получаем 4000000000. 4 или 8 гигабайт.
Сделаем фантастическое допущение, что все эти четыре гигабайта каким‐то образом влезут в оперативную память.

Однако ёмкость очереди сообщений Windows не настолько большая, и на десяти тысячах сообщений их уже откинет.
 
timurar77Дата: Пятница, 15.07.2022, 21:17 | Сообщение # 14
Рядовой
Группа: Пользователи
Сообщений: 8
Репутация: 0
Статус: 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
Репутация: 50
Статус: Offline
Загрузил винду и попробовал. Походу я не прав. Система судя по всему такие сообщения как PBM_SETPOS все таки внутри обрабатывает и даже обновляет интерфейс. Видно , что при больших нагрузках (отправке сообщений сотнями миллионов) все плющит , но она пытается и даже подвешивая программу все таки через какое-то время доходит до конца. Полагаться на такой алгоритм работы я бы точно не стал. Это может работать , а может и все встать в любой момент. Я бы обработку визуальной части прогрессбара поместил бы в таймер. Больше мне сказать нечего.

Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
  • Страница 1 из 2
  • 1
  • 2
  • »
Поиск: