Window not responding after a few seconds

Just starting out? Need help? Post your questions and find answers here.
MrCor
User
User
Posts: 22
Joined: Tue Dec 01, 2015 8:31 pm

Window not responding after a few seconds

Post by MrCor »

Hi guys and dolls,

I have coded the following and the windows freezes after a few seconds with the message 'not responding'. The progressbargadget gets stuck and the counter also stops.
What am I doing wrong here? (Dont get upset about the Dutch language)
BTW, I get this problem often with the same sort of constructions.

Code: Select all

;- CRC32 info ophalen uit bestanden
; scherm openen voor presentatie voortgang
OpenWindow(0, 0, 0, 320, 90, "Ophalen CRC32 info", #PB_Window_ScreenCentered)
ProgressBarGadget (0,  10, 10, 300, 30, 0, Aantal)
TextGadget (1, 150, 50, 200, 30, "")
UseCRC32Fingerprint()
Structure info
  Bestandsnaam.s
  CRC32.s
EndStructure
Dim Bestanden.info(0)
ExamineDirectory(0, PathData$, "*.jpg")
AantalBestanden = 0

While NextDirectoryEntry(0)
  AantalBestanden = AantalBestanden + 1
  ReDim Bestanden(AantalBestanden)
  Bestandsnaam$ = DirectoryEntryName(0)
  Bestanden(AantalBestanden)\Bestandsnaam = Bestandsnaam$
  Bestanden(AantalBestanden)\CRC32 = UCase(FileFingerprint(PathData$ + Bestandsnaam$, #PB_Cipher_CRC32))
  SetGadgetState(0, AantalBestanden)
  SetGadgetText(1, Str(AantalBestanden) + " / " + Str(Aantal))
Wend
FinishDirectory(0)
SortStructuredArray(Bestanden(), #PB_Sort_Ascending, OffsetOf(info\Bestandsnaam), TypeOf(info\Bestandsnaam))
CloseWindow(0)

// Code Tags added (Kiffi)
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Window not responding after a few seconds

Post by Fred »

You need an event loop. If you don't want to process the event just put:

Code: Select all

While WindowEvent() : Wend
in your while loop
MrCor
User
User
Posts: 22
Joined: Tue Dec 01, 2015 8:31 pm

Re: Window not responding after a few seconds

Post by MrCor »

Thanks Fred, you are the best. A simple solution I seem not able to come up with. Works fine now and future programs will also from now on.

Cheers, Cor
AZJIO
Addict
Addict
Posts: 2143
Joined: Sun May 14, 2017 1:48 am

Re: Window not responding after a few seconds

Post by AZJIO »

You need to add examples to the help. For a long time I could not understand why I cannot inform the user about the status of the processing process. I had to run the procedure in a separate thread and it didn't work on Linux. But still the question remains why not all messages get into the status bar. The window cannot be processed slower than the delay in the loop. At the moment I'm testing on Linux. I have long marked this topic for myself in the plan for updating my programs, since I already wrote them incorrectly.

Code: Select all

If OpenWindow(0, 0, 0, 300, 100, "StatusBar", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
	If CreateStatusBar(0, WindowID(0))
		AddStatusBarField(#PB_Ignore)
	EndIf
	StatusBarText(0, 0, "PureBasic, started")

	ButtonGadget (1, 10, 10, 200, 30, "Start")

	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_Gadget
				Select EventGadget()
					Case 1
						For i = 0 To 40
							Delay(100)
							StatusBarText(0, 0, Str(i))
							WindowEvent()
						Next
				EndSelect
			Case #PB_Event_CloseWindow
				CloseWindow(0)
				End
		EndSelect
	ForEver
EndIf
infratec
Always Here
Always Here
Posts: 7582
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Window not responding after a few seconds

Post by infratec »

Sorry to say that, but the coding is ... bad.

Still valid:
There can be only one
Only one event loop in a program.
Else you loose events or handle them at the wrong place ... (try to close your window while it is counting)

To avoid your construct there are 2 possibilies:

1. Use a timer
2. Use a thread

If you want to be crossplatform:
Only do GUI stuff in the main thread where your event loop is running.
Use PostEvent() to tell the main thread that something is to do in the GUI.

Example for 1 (timer):

Code: Select all

EnableExplicit


Define Exit.i, i.i

If OpenWindow(0, 0, 0, 300, 100, "StatusBar", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
  If CreateStatusBar(0, WindowID(0))
    AddStatusBarField(#PB_Ignore)
  EndIf
  StatusBarText(0, 0, "PureBasic, started")
  
  ButtonGadget (1, 10, 10, 200, 30, "Start")
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Timer
        If EventTimer() = 1
          StatusBarText(0, 0, Str(i))
          i + 1
          If i = 41
            RemoveWindowTimer(0, 1)
          EndIf
        EndIf
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 1
            AddWindowTimer(0, 1, 100)
        EndSelect
      Case #PB_Event_CloseWindow
        CloseWindow(0)
        Exit = #True
    EndSelect
  Until Exit
EndIf

Example for 2 (thread):

Code: Select all

CompilerIf Not #PB_Compiler_Thread
  CompilerWarning "You should enable Threadsafe in compiler options"
CompilerEndIf
  
EnableExplicit

Enumeration #PB_Event_FirstCustomValue
  #OwnEvent_UpdateStatusBar
EndEnumeration



Procedure Thread(*Exit.Integer)
  
  Protected i.i
  
  For i = 0 To 40
    PostEvent(#OwnEvent_UpdateStatusBar, 0, 0, 0, i)
    Delay(100)
    If *Exit\i
      Break
    EndIf
  Next i
EndProcedure


Define Exit.i, Thread.i


If OpenWindow(0, 0, 0, 300, 100, "StatusBar", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
  If CreateStatusBar(0, WindowID(0))
    AddStatusBarField(#PB_Ignore)
  EndIf
  StatusBarText(0, 0, "PureBasic, started")
  
  ButtonGadget (1, 10, 10, 200, 30, "Start")
  
  Repeat
    Select WaitWindowEvent()
      Case #OwnEvent_UpdateStatusBar
        StatusBarText(0, 0, Str(EventData()))
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 1
            Thread = CreateThread(@Thread(), @Exit)
        EndSelect
      Case #PB_Event_CloseWindow
        CloseWindow(0)
        Exit = #True
    EndSelect
  Until Exit
  
  If Thread
    If WaitThread(Thread, 2000) = 0
      Debug "Should never been reached"
      KillThread(Thread)
    EndIf
  EndIf
  
EndIf
Last edited by infratec on Sat Apr 29, 2023 9:07 am, edited 8 times in total.
User avatar
Caronte3D
Addict
Addict
Posts: 1355
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: Window not responding after a few seconds

Post by Caronte3D »

I think is better not use more than a WindowEvent() function, because you can lost other messages while in the "For" loop

And if you need a very acurate constant speed of refresh, is better to use a Thread (less precission: Timer or a timeSetEvent_).

Code: Select all

If OpenWindow(0, 0, 0, 300, 100, "StatusBar", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
	If CreateStatusBar(0, WindowID(0))
		AddStatusBarField(#PB_Ignore)
	EndIf
	StatusBarText(0, 0, "PureBasic, started")

	ButtonGadget (1, 10, 10, 200, 30, "Start")
	
	Define i=41
	Repeat
		Select WaitWindowEvent(100)
			Case #PB_Event_Gadget
				Select EventGadget()
				  Case 1
				    i=0
				EndSelect
			Case #PB_Event_CloseWindow
				CloseWindow(0)
				End
		EndSelect
		
		If i<=40
		  StatusBarText(0, 0, Str(i))
		  i+1
  	EndIf
		
	ForEver
EndIf
EDIT: infratec was faster :D
AZJIO
Addict
Addict
Posts: 2143
Joined: Sun May 14, 2017 1:48 am

Re: Window not responding after a few seconds

Post by AZJIO »

Caronte3D wrote: Sat Apr 29, 2023 8:51 am

Code: Select all

		If i<=40
		  StatusBarText(0, 0, Str(i))
		  i+1
If by button id=1 I launch a function that will search for files for 5 minutes, calculate MD5, then the window will freeze, since the events servicing the window do not return to the window and the system marks it as hung. In this case, the StatusBarText(0, 0, Str(i)) you specified will not be called. Then when my function ends, your function StatusBarText(0, 0, Str(i)) will be called. But it won’t matter to me anymore, since it was important for me to write a log at the moment when my function works, so that the user knows what is happening. And when it ends, it won't matter anymore.

infratec
I now have all the numbers displayed in Linux, I'll try this option, maybe I've already tried it, but the difference is that instead of Delay(100), my procedure loads the processor to the maximum (calculating MD5), will the timer work at the same time ... It will be necessary try.
AddWindowTimer()
The timer events will only be generated when there are no other events to be processed (timers are low-priority events).
User avatar
Caronte3D
Addict
Addict
Posts: 1355
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: Window not responding after a few seconds

Post by Caronte3D »

I don't think hangs the event loop with a very time consuming is good idea at all, on this case a thread is a must to prevent the app hang.
Anyway each programmer knows what want to do with her program.
infratec
Always Here
Always Here
Posts: 7582
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Window not responding after a few seconds

Post by infratec »

@AZJIO
For something you need definately a thread and not a timer.

If your code inside the timer event takes long, it still blocks the main loop.
Exactly for this are threads.
AZJIO
Addict
Addict
Posts: 2143
Joined: Sun May 14, 2017 1:48 am

Re: Window not responding after a few seconds

Post by AZJIO »

Caronte3D wrote: Sat Apr 29, 2023 9:55 am I don't think hangs the event loop with a very time consuming is good idea at all, on this case a thread is a must to prevent the app hang.
The event loop is a standard loop, there is nothing magical about it. Only the WaitWindowEvent() event allows a window to perform window system maintenance. If I call WindowEvent(), I do the same, but without using the delay created by WaitWindowEvent(), so as not to make the loop too fast and thereby strain the processor.
User avatar
Caronte3D
Addict
Addict
Posts: 1355
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: Window not responding after a few seconds

Post by Caronte3D »

If while in the For a message like mouse click, resizewindow, etc... comes, that message is skiped because you don't process it inside the for loop.
AZJIO
Addict
Addict
Posts: 2143
Joined: Sun May 14, 2017 1:48 am

Re: Window not responding after a few seconds

Post by AZJIO »

@infratec
I have said more than once that I came with AutoIt3. I don't know the internals of AutoIt3, but when I call the paste text function on any element of the window, it will not be pasted in a parallel stream, but as a sequential boolean event. That is, if I make the output of the processed files in the status bar, then it flickers without missing a single file. At the same time, redrawing the window naturally leads to a slowdown in the operation, so I made a counter, when the sum of file sizes reaches 10 MB, the function inserts the current file into the status bar, so 100 KB files are not inserted, but only when 100 files are found, only then will write one file, while the text in the status bar changes 3 times per second (depending on the speed of the disk) and this is enough for the user to monitor the progress of file processing.
In PureBasic, on the contrary, I cannot get all the data to be output.
Caronte3D wrote: Sat Apr 29, 2023 10:13 am If while in the For a message like mouse click, resizewindow, etc... comes, that message is skiped because you don't process it inside the for loop.
If you have set the settings for searching for files and the operation is running, then why do you click on the buttons? Usually, in this case, I deactivated all the buttons that might interfere with the process. I only add a button to abort the operation and check if that button has been started. Whatever the user had to press, he had to do it before starting file processing or any other calculations. Usually I block everything, leaving only the information output elements and the button to cancel the operation working.
AZJIO
Addict
Addict
Posts: 2143
Joined: Sun May 14, 2017 1:48 am

Re: Window not responding after a few seconds

Post by AZJIO »

infratec wrote: Sat Apr 29, 2023 8:45 am Still valid:
There can be only one
Only one event loop in a program.
Here is an example of 2 loops
viewtopic.php?t=81357
Although I block the window, so the event processing for it stops.
In my case, I do not need to receive window events when a file processing operation is in progress. I do not exclude that system events could be processed, for example, window resizing, although it is not critical, even if this is not available. My task is to output data to the status bar. If the user does not see what is happening, the speed of operations, is there a failure when it is impossible to access the broken file, then it is useless to wait for the completion of the operation that will not be completed or the user does not want to wait a long time or the user sees that he made a mistake, because in the status bar extraneous files
User avatar
mk-soft
Always Here
Always Here
Posts: 6207
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Window not responding after a few seconds

Post by mk-soft »

For some GUI actions, the OS pauses the event until the action is finished.
PostEvent, however, continues to append the events. When the OS action is finished, all events accumulated up to that point are processed.

If a user query must be executed by the thread, this can only be done via PostEvent and Semaphore.
I have added an example 5 in the Mini Thread Control.

Link: Mini Thread Control
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
infratec
Always Here
Always Here
Posts: 7582
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Window not responding after a few seconds

Post by infratec »

@AZJIO

Your example with 2 event loops is, in my opinion, not a good solution.
The same behaviour can be done with one event loop.

Or, use the BindEvent stuff instead of a second loop to get the modal behavior.

And your example should use #PB_Any for Gadgets and Window, to be independent from the main code.
Then you can put it in a pbi and use it in different programs without any risk.

But many ways are possible and at least it is your decision.
Post Reply