Nick Craig-Wood wrote: > > Here is test prog... > <snip>
Here's a more real-life like program done in both single threaded mode and multi-threaded mode. You'll need PythonCard to try this. Just to make the point, you will notice that the core code is identical between the two (method on_menuFileStart_exe). The only difference is in the setup code. I wanted to dismiss the myth that multi-threaded programs are inherently *evil*, or that it's diffcult to code, or that it's unsafe.....(what ever dirty water people wish to throw at it). Don't ask me to try this in process! To have fun, first run it in single threaded mode (change the main program to invoke the MyBackground class, instead of the MyBackgroundThreaded class): Change: app = model.Application(MyBackgroundThreaded) to: app = model.Application(MyBackground) Start the process by selecting File->Start, and then try to stop the program by clicking File->Stop. Note the performance of the program. Now, run it in multi-threaded mode. Click File->Start several times (up to 4) and then try to stop the program by clicking File->Stop. If you want to show off, add several more StaticText items in the resource file, add them to the textAreas list in MyBackgroundThreaded class and let it rip! BTW: This ap also demonstrates the weakness in Python thread - the threads don't get preempted equally (not even close). :-) Two files follows (test.py and test.rsrc.py): #!/usr/bin/python """ __version__ = "$Revision: 1.1 $" __date__ = "$Date: 2004/10/24 19:21:46 $" """ import wx import threading import thread import time from PythonCard import model class MyBackground(model.Background): def on_initialize(self, event): # if you have any initialization # including sizer setup, do it here self.running(False) self.textAreas=(self.components.TextArea1,) return def on_menuFileStart_select(self, event): on_menuFileStart_exe(self.textAreas[0]) return def on_menuFileStart_exe(self, textArea): textArea.visible=True self.running(True) for i in range(10000000): textArea.text = "Got up to %d" % i ## print i for j in range(i): k = 0 time.sleep(0) if not self.running(): break try: wx.SafeYield(self) except: pass if not self.running(): break textArea.text = "Finished at %d" % i return def on_menuFileStop_select(self, event): self.running(False) def on_Stop_mouseClick(self, event): self.on_menuFileStop_select(event) return def running(self, flag=None): if flag!=None: self.runningFlag=flag return self.runningFlag class MyBackgroundThreaded(MyBackground): def on_initialize(self, event): # if you have any initialization # including sizer setup, do it here self.myLock=thread.allocate_lock() self.myThreadCount = 0 self.running(False) self.textAreas=[self.components.TextArea1, self.components.TextArea2, self.components.TextArea3, self.components.TextArea4] return def on_menuFileStart_select(self, event): res=MyBackgroundWorker(self).start() def on_menuFileStop_select(self, event): self.running(False) self.menuBar.setEnabled("menuFileStart", True) def on_Stop_mouseClick(self, event): self.on_menuFileStop_select(event) def running(self, flag=None): self.myLock.acquire() if flag!=None: self.runningFlag=flag flag=self.runningFlag self.myLock.release() return flag class MyBackgroundWorker(threading.Thread): def __init__(self, parent): threading.Thread.__init__(self) self.parent=parent self.parent.myLock.acquire() threadCount=self.parent.myThreadCount self.parent.myLock.release() self.textArea=self.parent.textAreas[threadCount] def run(self): self.parent.myLock.acquire() self.parent.myThreadCount += 1 if self.parent.myThreadCount==len(self.parent.textAreas): self.parent.menuBar.setEnabled("menuFileStart", False) self.parent.myLock.release() self.parent.on_menuFileStart_exe(self.textArea) self.parent.myLock.acquire() self.parent.myThreadCount -= 1 if self.parent.myThreadCount==0: self.parent.menuBar.setEnabled("menuFileStart", True) self.parent.myLock.release() return if __name__ == '__main__': app = model.Application(MyBackgroundThreaded) app.MainLoop() Here's the associated resource file: {'application':{'type':'Application', 'name':'Template', 'backgrounds': [ {'type':'Background', 'name':'bgTemplate', 'title':'Standard Template with File->Exit menu', 'size':(400, 300), 'style':['resizeable'], 'menubar': {'type':'MenuBar', 'menus': [ {'type':'Menu', 'name':'menuFile', 'label':'&File', 'items': [ {'type':'MenuItem', 'name':'menuFileStart', 'label':u'&Start', }, {'type':'MenuItem', 'name':'menuFileStop', 'label':u'Sto&p', }, {'type':'MenuItem', 'name':'menuFile--', 'label':u'--', }, {'type':'MenuItem', 'name':'menuFileExit', 'label':'E&xit', 'command':'exit', }, ] }, ] }, 'components': [ {'type':'StaticText', 'name':'TextArea1', 'position':(10, 100), 'text':u'This is a test', 'visible':False, }, {'type':'StaticText', 'name':'TextArea2', 'position':(160, 100), 'text':u'This is a test', 'visible':False, }, {'type':'StaticText', 'name':'TextArea3', 'position':(10, 150), 'text':u'This is a test', 'visible':False, }, {'type':'StaticText', 'name':'TextArea4', 'position':(160, 150), 'text':u'This is a test', 'visible':False, }, ] # end components } # end background ] # end backgrounds } } -- http://mail.python.org/mailman/listinfo/python-list