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

Reply via email to