Thread, Process and Game Loop

@agoose77: I don’t know how to use your class QueuedThread, but here is an example of code:
Il you tell me how to use it, i can test


import bge
import threading
from time import sleep

def task(i):
    for n in range(0,i):
        print ("Hello ",n)
        sleep(1)

def test(cont):
    if not cont.sensors[0].positive:
           return

    print("Call n°",bge.call)
    bge.call += 1
    
    thread = threading.Thread(target=task,args=(10,))
    thread.start()
    #thread.join()

test is called by a controller type module, link to a keyboard sensor.
If we use join : the game is freezed until task done, it’s normal.
If we don’t use join, the tasks will be “running” only during controller execution time.

Of course-you’re calling the function inside of the controllers’s code.

If you want to run a separate thread that manages its own state, then you simply need to ask the thread to continue to function. I’m using a while loop which consumes tasks from a queue. Queues can be used to ensure we don’t incur resource conflicts during execution. You do not have to subclass to utilise this while loop, just pass a function which includes one. You’ll see it continues to execute outside of the main controller. The act of spawning a thread is sometimes rather costly, better to reuse one (which is why a consumer is better than a single delegate)

Thank you agoose, but i don’t know if it’s because of my shortcomings in the English language, but I’m not sure I understand.
So if I want the task to run in parallel mode, I have to create it (thread = threading.Thread(target=task,args=(10,)) where ? outside the controller, it’s in the python code globally ?
Like that in a script (no module call):


import threading
from time import sleep

def task(i):
    for n in range(0,i):
        print ("Hello ",n)
        sleep(1)


thread = threading.Thread(target=task,args=(10,))
thread.start() 

Yes it functions… but why not in a controller ?

That is what you’re does. The problem is that it is a short function and so it ends in the time between execution of controllers. So it appears to block. But if you create a governing while loop that runs whatever code you like whilst you want it to - as I have done with the isSet attribute check - then it can run all the time.

Sent from my Nexus 5 using Tapatalk

IMPOSSIBLE…
I was I was persuaded that it worked yesterday, I even believe to have seen him working…
Could you test that ? It’s that simple code just above !
here is the blend file : test.blend (458 KB)

Have you this result in the console ?

Blender Game Engine Started
Hello 0
Blender Game Engine Finished
Hello 1
Hello 2
Hello 3
Hello 4
Hello 5
Hello 6
Hello 7
Hello 8
Hello 9

If it’s like that, threads doesn’t function. I’ve waited during 1 minute before pressing ESC
@agoose77: could you send me a code that do what i wan’t : drawing hello in a loop with sleep(1) in // mode please ? It’s a short function, but it’s executing during 10 sec. I’ve also a most sophisticated functions, but it’s the simple example i’ve found to show the problem. I’ve converted the function with multiprocessing and it’s functionning well - but i would like to understand what it means with the threads under BGE : i haven’t this with pyhton not under Blender.

That works, what are you trying to achieve?

I want that :

Blender Game Engine Started
Hello 0
Hello 1
Hello 2
Hello 3
Hello 4
Hello 5
Hello 6
Hello 7
Hello 8
Hello 9
Blender Game Engine Finished

But not with a join ! I want the task to run in // ! What have you ?

Run it in module mode.


import threading
from time import sleep


def task(i):
    for n in range(0,i):
        print ("Hello ",n)
        sleep(1)
    print("RUN")


def main(cont):
    own = cont.owner
    if not "s" in own:
        own['s']=1
        thread = threading.Thread(target=task,args=(10,))
        thread.start()

Python Module:

“test.main”

That does’t function. If you don’t call main in a loop (not RunOnce), that do the same thing.
I understand what you did : you are calling with an “always” sensor with “activate on true level triggering” to call in loop test.main().
You illustrate that the thread is not in // mode, because you must call everytime the function which had created the thread.
Even if you control (whith s property) if the thread have been already created, you give some “cpu time” to the function (main) which is the parent of the task.
What i want is a thread that is running in // of all other tasks, not only the main function, a task wich can be alive all the time !

Are we now agree on how threads are functionning under Blender ?

Run the file, and tell me that it doesn’t work. I’ll acknowledge that the file demonstrated does not work, but the file that I have shown you how to create does. I can only guess that it is something to so with the import mechanism that breaks it.

Sent from my Nexus 5 using Tapatalk

If i use a sensor “always” (only run once), i obtain the same result:

Blender Game Engine Started
Hello 0
Blender Game Engine Finished
Hello 1
Hello 2
Hello 3
Hello 4
Hello 5
Hello 6
Hello 7
Hello 8
Hello 9

Are you using a sensor “always” with “activate on True Level Triggering” with a certain frequency ?
If you use that, this means that my explaination is good : the task run not in // of Blender, it only running in // during the time of “python controller”. For example, if i launch another script every cycle, the precedent thread will continue to run. But if i don’t call another python script, the thread is “freezed”.
It’s the main difference between task and process : under blender, python scripts don’t run at all the time. So threads not too.
But process are really in // mode. We call a function with multiprocessing one time, and it’s running in // until it ends.

I stand corrected, you are correct.

Thank you for your follow : it was important for me to understand the threading under Blender (book).
Now, i have another problem : multiprocessing do what i want. But, when exiting, the subs are ending well, but the main process not. Blender seems to have been forked, but not accessible. I must kill the process with system tools…

I’m missing something…
Does anybody has used multiprocessing without that problem ?

I’ve found the problem with multiprocessing: i’ve used a Manager object - it creates “also” a fork project ! We must shutdown it, otherwise it’ll be still alive after quit the game.