For others that don’t want to download the zip. I am showing the new version of @Daniel1 code.
Calling procedure (Main)
ThreadCounter LONG(3)
ThreadQ Queue
Thread SIGNED
END
!Button 1 press
glo:MainThread = THREAD()
ThreadQ.Thread= start(MyProcedure, 35000, ThreadCounter)
ADD(ThreadQ)
resume(ThreadQ.Thread) !probably not needed?
!ThisWindow.TakeNotify PROCEDURE(UNSIGNED NotifyCode,SIGNED Thread,LONG Parameter)
ThreadCounter -= 1
IF ThreadCounter > 0
ThreadQ.Thread= start(MyProcedure, 35000, ThreadCounter)
ADD(ThreadQ)
resume(ThreadQ.Thread) !Probably not needed
END
MyProcedure thread code
TimerLength LONG(1) !Adjust as required
FirstTime LONG(TRUE) ! Initialize to TRUE in the beginning of processing
EndOfFileFlag LONG(FALSE) ! Track if weve reached the end of the file
RecordsProcessed LONG ! Counter for how many records processed in each timer event
MaxRecordsPerCycle EQUATE(1000) !Adjust as required
L LONG
!OF EVENT:OpenWindow
0{prop:timer} = TimerLength !Start timer
NOTIFY(0,glo:MainThread) !Notify starting thread that we are open
!OF EVENT:Timer
0{PROP:Timer} = 0 ! Disable timer while processing
IF L >= mLoop * 10
0{prop:text} = 'DONE! - SHOULD CLOSE NOW'
POST(EVENT:CloseWindow) ! Post a close window event
ELSE
IF FirstTime
CLEAR(m:record) ! Clear the record buffer
SET(m:idKey, m:idKey) ! Set key for the table (only once, on first event)
FirstTime = FALSE ! Set flag to indicate we no longer need to start from the beginning
END
IF NOT EndOfFileFlag
! Process X records in each timer event
RecordsProcessed = 0
LOOP
IF Access:MyTable.Next() <> Level:Benign
EndOfFileFlag = TRUE ! Set the flag when no more records
BREAK
END
! Increment the processed counter
RecordsProcessed += 1
! Update the window's text field with progress
0{PROP:Text} = 'Cycle: ' & mLoop & ' Done: ' & FORMAT(L/(mLoop*10)*100,@n02) & '% - Thread: ' & THREAD() & ' Time: ' & FORMAT(CLOCK(), @t4)
! Exit after processing 10 records in this timer event
IF RecordsProcessed >= 1000
BREAK
END
END
END
IF EndOfFileFlag
L += 1 ! Increment when all records are processed
! Reset flags to allow the process to start again if needed
EndOfFileFlag = FALSE ! Reset the end of file flag
FirstTime = TRUE ! Set FirstTime to TRUE if we want to reset the table for the next cycle
END
0{PROP:Timer} = TimerLength ! Re-enable the timer
END
You need 2 commas, the POST(, Thread,1) is the 3rd parameter. You probably want to add a “,1” as the 4th parameter to place your Close event 1st in the message queue.
The Clarion Help is really good and always worth a quick read when code is not working.
@CarlBarnes Thanks but it don’t work
The code is inside Window.TakeEvent procedure and it does not send that POST to window because it is “locked” until previous dialog/thread is not cloded.
If the code is not inside TakeEvent, then it is not executed at all.
You can check sample if you want (it is here). @Mark_Sarson wrote another sample of how to deal with database records - now I need to figure out how to use their code for other processes like backup procedure, export to Excel etc.
Once you find what you need, I agree that the help is very good.
I find the Clarion help to work best when I already know the answer (and where to find it). But I know there have been plenty of frustrated people looking for help in the forums because they can’t find what they’re looking for.
I dont think the [,control] is “optional”, I think it needs to be just left blank eg.
POST( event , [control] [,thread] [,position] )
I think POST is a RTL wrapper of sorts for this API which also doesnt have wParam or lParam as optional, but 0 aka null is still a valid value and the Post might have its procedure parameters defined as ‘=0’ for default values. PostMessageA function (winuser.h) - Win32 apps | Microsoft Learn
Yeah but I found one or two clarion functions where it needed a double comma as it could not be used optionally, hence the “, [param] ,” and not “[, param],”
When I get a chance I’ll go back through my code to highlight them, but it was on a win10 Pro dev machine, but I thought Post was one of them, hence why I said what I said.
All I can tell you with certainty is POST(Event:CloseWindow , , GLO:Thread) with
2 Commas and no Control is the correct syntax to send a Window event to another thread. POST() does not require a Control number, those are called Window Events.
You must have some other problems with your code. The value of GLO:Thread must be correct. That Thread must have an ACCEPT loop active and not blocked. The code must be in the correct place where Window Events are handled It must handle the event correctly, likely a BREAK. Etc. Sorry I cannot help with these currently.
@CarlBarnes I understand that POST(Event:CloseWindow (or Return Level:Fatal) will work if everything is correct with the code. I posted example here and I know that code is not correct (I don’t know how to write correct code , otherwise I will not even started this thread).
It utilizes some of my alterations in my first response, but doesn’t use the stepped processing using the timer of that example.
Instead it uses a separate code template procedure for the processing. So the “MyProcedure” procedure “STARTS” a new thread, CodeThread.
Please study everything in the example, as there are a lot of changes, including an embed in the Global Embeds.
NOTIFY is used extensively, and it is worth studying this.
And finally, please, understand that you should never put code for processing anything in the .TakeEvent embed. Note how I have used a specific Event (EVENT:OpenWindow) to do what was needed.
Again, there is a lot to study, as I can’t really describe everything being done here.
@Mark_Sarson
Now it is OK, thank yo again, so I started testing different scenarios.
So I changed “CodeThread” procedure like this
!Assign NotifyGroup to the passed address of the notify group
NotifyGroup &= (ngAddress)
DO OpenFiles
loop L = 1 to (mLoop * 1000)
clear(m:record)
!set(m:idKey,m:idKey)
!loop until access:myTable.next() <> level:benign
!Code to process here
m:name = 'Thread ' & THREAD() & ' - loop ' & L
if access:myTable.insert() <> level:benign
stop('Insert Error: '&errorcode()&' : '&error())
end
!END
!Fill notify group with values
NotifyGroup.PercentComplete = L/(mLoop*10)*100
NotifyGroup.OtherParam1 = 'Thread ' & THREAD() & ' - loop ' & L
NOTIFY(NOTIFY:DisplayUpdate, threadID)
END
!Finished, so notify caller we have finished
NOTIFY(NOTIFY:ProcessingComplete, threadID)
DO CloseFiles
and I clicked on “Run MyProc” few times - this is what is happened: