PDA

View Full Version : Multithreading in Vizard 3.0


RedSpikeyThing
02-19-2008, 01:22 PM
I'm currently using Vizard 3.0 and having trouble getting a simple multithreaded application to run. I wrote a script in IDLE using Python 2.3 (the same version as Vizard) and it works as expected. When it is run in Vizard, however, I get the following error:

"Unhandled exception in thread started by
Error in sys.excepthook:
Original exception was:
Unhandled exception in thread started by
Error in sys.excepthook:
Original exception was:
Unhandled exception in thread started by
Error in sys.excepthook:
Original exception was:
Unhandled exception in thread started by
Error in sys.excepthook:
Original exception was:"

The code is pretty simple and, as I said before, works as expected in IDLE.

import thread

def countingThread(id, maxVal):
global printLock
for i in range(maxVal):
printLock.acquire()
print "Thread ", id, ": ", i
printLock.release()

global printLock
printLock = thread.allocate_lock()
for i in range(5):
thread.start_new_thread(countingThread, (i, 50))

Any help would be greatly appreciated!!

farshizzo
02-19-2008, 02:10 PM
The problem is that your script does not wait for the threads to complete before exiting. I've modified your script to use the more advanced threading module. It will also wait for all the threads to complete before exiting. Here is the code:import threading

#Create mutex for printing
printLock = threading.Lock()

def countingThread(id, maxVal):
global printLock
for i in range(maxVal):
printLock.acquire()
print "Thread ", id, ": ", i
printLock.release()

threads = []
for i in range(5):
#Create and start the threads
t = threading.Thread(target=countingThread, args=(i, 50))
t.start()

#Save thread object to list
threads.append(t)

#Wait for threads to complete
for t in threads:
t.join()

RedSpikeyThing
02-19-2008, 02:24 PM
Great, thank you! Is there any reason this works correctly in IDLE but not in Vizard?

farshizzo
02-19-2008, 02:28 PM
Technically, your code should not work. I think the reason it works with IDLE is that IDLE runs the script in its embedded interpreter, which does not exit until the GUI is closed. If you ran the script directly from the command line, my guess would be that it would have the same problem as Vizard.

RedSpikeyThing
02-20-2008, 11:32 AM
That makes sense. I have one more question:

I would like to run a thread that monitors a bunch of sensors for a particular pattern. I set up a deamon thread that runs in a "while true:" loop, but this is still causing some problems.

I also considered setting this up as an event, but I don't see how I can build a custom event that requires parameters being passed to the constructor.

This is getting very frustrating because what I want to do is conceptually simple, but seems to be difficult to implement. Any advice would be appreciated.

farshizzo
02-20-2008, 11:38 AM
What is the problem with your "while True:" loop? Are you yielding to other threads in the loop by issuing a time.sleep(...) call?

Are you talking about a custom threading event or a Vizard event?

RedSpikeyThing
02-20-2008, 12:30 PM
What is the problem with your "while True:" loop? Are you yielding to other threads in the loop by issuing a time.sleep(...) call?

Are you talking about a custom threading event or a Vizard event?

The code I am using is supposed to spew out number until the program stops:
import viz
import threading

class ThreadedClass (threading.Thread):
def run(self):
i = 0
while True:
i = i + 1
print i

t = ThreadedClass()
t.setDaemon(True)
t.start()

viz.go()

This code should just print successive numbers until the program is terminated. The output I get, however, is as follows:

1
2
<you get the idea>
1051
** Load Time: 0.12 seconds
1052
1053
<you get the idea>
1066

No matter how long the program is run for, it terminates at 1066. Also, the numbers 1052 to 1056 do not appear in the output window until the main program is stopped. It appears as if the thread is not running past a certain number of iterations.

I've been looking around for resources on how to do this, but I am having difficulty finding any. Do you have any references so that I don't have to post for every problem I encounter?

As always, thanks I appreciate the help.

farshizzo
02-20-2008, 12:42 PM
Try adding the following line to your script:viz.directormode(viz.DIRECTOR_FAST)This tells Vizard to allow Python threads to run while Vizard is drawing. Technically speaking, this will instruct Vizard to relase the GIL while rendering. For more information about the GIL and how Python threads behave, have a look at this page, http://docs.python.org/api/threads.html

RedSpikeyThing
02-20-2008, 12:48 PM
Wow you're quick on the draw. That worked perfectly! Thanks for the help and the reference....hopefully I won't have to bug you anymore ;)

Gladsomebeast
10-17-2008, 05:05 PM
Is using threading.Threads objects possible while running a Vizard sim without the viz.directormode call? In other words, must you set the director mode when you want to run threading.Threads while running a Vizard sim?

farshizzo
10-17-2008, 05:16 PM
It depends. The call to viz.directormode(viz.DIRECTOR_FAST) simply tells Vizard to allow other Python threads to run while it is rendering. If you don't have this flag set, then the only time your Python thread will run is after 100 Python virtual instructions have been executed in the main thread (see sys.setcheckinterval in the Python docs for more info).

If your thread is only performing computations or file i/o, then I would recommend setting this flag. If your thread is modifying the Vizard scene graph, then I would NOT set this flag.