Thanks for contributing.
Using Windows API calls is some advanced stuff. In the interest of being constructive I will begin poking holes.
Clarification: This technique is a time based "interrupt" and is supposed to stop the program execution (to interrupt it) so that the interrupt code can be run. Then the execution returns to where the game left off and continues along like nothing happened. To be clear this is not multi-threading.
Real World Test
This code is the example code modified to load The Matrix movie in looped batches of 20 to simulate real world media loading. The program has also been modified to post the timestamps of the interrupts down the left side of the window.
Rem ***** Main Source File *****
init:
global counter
global ittext$
sync on
sync rate 60
backdrop on
Dim times(100)
user32DLL = 1
timerdelay = 1000 `timer delay in milliseconds
x = screen width() / 2
y = screen height() / 2 +50
text$ = "mainloop is dooing this..."
set window title "Interrupt Timer by Code Maker 2017"
`load user 32 bit dll
load dll "user32.dll", user32DLL
`get window handle, identifies the window to be associated with the timer
WindowHWND = call dll(user32DLL, "GetActiveWindow")
`get pointer to function
InterruptTimerPTR = get ptr to function("InterruptTimer")
`make timer, it starts immediately
TimerID = call dll(user32DLL, "SetTimer", WindowHWND, 1, timerdelay, InterruptTimerPTR)
`main loop
do
dec x
dec y
if x<-text width(text$) then x=screen width()
if y<-text height(text$) then y=screen height()+15
if inkey$()<>"" then exit
sync
Load_MediaItem()
text x, 200, text$
text screen width()/2-text width(ittext$)/2, y, ittext$
For i = 1 to 100
If times(i) > 0 Then text 10, i * 20, str$(abs(times(i) - times(1)))
Next i
loop
`clean up before exit
s = call dll(user32DLL, "KillTimer", WindowHWND, TimerID)
delete dll user32DLL
`exit program
end
`function, this is what the interrupt timer will do
function InterruptTimer()
inc counter
ittext$ = "interrupt timer is doing this, without any calls from the mainloop " + str$(counter)
times(counter) = timer()
endfunction
Function Load_MediaItem()
For i = 1 to 20
Load Animation "TheMatrix.avi", 1
Delete Animation 1
Next i
EndFunction
The Result
As you can see there are times in milliseconds listed down the left side of the window. They are how much time passed since the first interrupt since the numbers are easier to read this way than huge long timer values.
What Does This Mean?
1. Loading media can and does delay the interrupts. Look at the times they should be 1000ms apart. They are not. So this has no real advantage over updating the screen between loaded items.
2. Delayed interrupts begin to stack up. Look at the times, many of them are grouped on the same/similar time as the interrupt before. This means that hell or high water you will execute every missed or delayed interrupt. You will delay loading more media until the program can catch up. So this is worse than traditional methods. It also means that backlogged "Interrupts" can interrupt other "Interrupts" as they stack making the program potentially unstable. I didn't test for it, but I would likely see some of those grouped Interrupts are out of order.
3. I have noticed that if the program crashes, this thing will make the program unresponsive and difficult to close. It interferes with the event handling of the mouse click in the error popup window. So this has compatibility problems.
Additional Gripes
4. It seems somewhat dangerous syncing the screen with media loading, in a manner where any indiscriminate place in the code could be stopped for a screen update or other things. One might expect screen oddities or even a crash in the worst case scenario. If you don't want your program to crash when the screen is locked or laptop lid is closed, you have to
handle recovering from a loss of screen device error. So if your interrupt updates the screen it also has to perform a recovery of all the loaded assets. Only now you have a half loaded level to recover, maybe you were mid way through setting up an asset like a character. Then the interrupt just ends and the program is supposed to pickup exactly where the loading left off. This would be a nightmare to manage. So now you are back in some function adding a shader to an object, only now the object is loaded under a different object index (if you even managed to perform a recovery) and the variable storing the objects index is wrong so the commands using it fail and the program crashes. Or you performed no recovery at all and the program crashes. You would have to load everything exactly the same even the half loaded asset whose setup was interrupted. Unrealistic.
5. There is an apparent lack of control. You are basically handing control of the visual flow over to windows.
Thoughts of actual multi-threading aside, why not just program the game to update the screen between loading items if more than 1000ms has passed since the last update?
Simpler, safer, more control, easier to read, more efficient.