@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()
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.
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.
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()
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.
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.
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.