Design Question: GUI+Threads.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Frithiof Andreas Jensen

    Design Question: GUI+Threads.

    Hi All,

    I am tinkering with a stock-market analysis program that needs to have (at
    least one) a worker thread for processing real-time data and a GUI where one
    can control/monitor the function of the worker, set parameters and so forth.

    Is there an elegant and generic way to implement the typical "Model, View,
    Controller" pattern so that the "Model+Controll er" execute in the context of
    the worker thread and the "View" will execute in the GUI thread - and
    communication between the two is thread-safe and simple?




  • Syver Enstad

    #2
    Re: Design Question: GUI+Threads.

    "Frithiof Andreas Jensen" <frithiof.jense n@removethis.te d.ericsson.dk> writes:
    [color=blue]
    > Hi All,
    >
    > I am tinkering with a stock-market analysis program that needs to have (at
    > least one) a worker thread for processing real-time data and a GUI where one
    > can control/monitor the function of the worker, set parameters and so forth.
    >
    > Is there an elegant and generic way to implement the typical "Model, View,
    > Controller" pattern so that the "Model+Controll er" execute in the context of
    > the worker thread and the "View" will execute in the GUI thread - and
    > communication between the two is thread-safe and simple?[/color]

    One way to do it:

    Use two Queue.Queue's. Do non blocking get's and put's from the gui on
    a timer. Do blocking gets from the queue instance that the GUI calls
    put on, do blocking put's on the queue that the GUI calls get from.

    I usually wrap the use of Queue behind a method interface, so that the
    GUI calls methods on the threaded class to get and put. If you want to
    to use a thread pool you can easily make all the threads can share the
    queue instances.

    Comment

    • Brian Kelley

      #3
      Re: Design Question: GUI+Threads.

      Syver Enstad wrote:
      [color=blue]
      > "Frithiof Andreas Jensen" <frithiof.jense n@removethis.te d.ericsson.dk> writes:
      >
      >[color=green]
      >>Hi All,
      >>
      >>I am tinkering with a stock-market analysis program that needs to have (at
      >>least one) a worker thread for processing real-time data and a GUI where one
      >>can control/monitor the function of the worker, set parameters and so forth.
      >>
      >>Is there an elegant and generic way to implement the typical "Model, View,
      >>Controller" pattern so that the "Model+Controll er" execute in the context of
      >>the worker thread and the "View" will execute in the GUI thread - and
      >>communicati on between the two is thread-safe and simple?[/color][/color]

      You might make your life easier by having the controller and the view be
      on the main thread and dispatch a new model to the work thread.

      Contoller -> starts or attaches to view
      -> starts a new model

      model -> signals events to controller which updates view
      controller -> sets model states when necessary.

      Usually you can wrap model events into gui events and let the gui's
      mainloop sort them out and dispatch them to the controllers callbacks.

      In python it is thread safe to set variables across the thread boundary,
      the model will have to check for these variables changing though. The
      standard variable is set by thread.kill() see the threading module for
      more details.

      What gui framework are you using?

      Brian Kelley

      Comment

      • Frithiof Andreas Jensen

        #4
        Re: Design Question: GUI+Threads.

        Thaks for the reply,

        "Brian Kelley" <bkelley@wi.mit .edu> wrote in message
        news:3f97ee4a$0 $573$b45e6eb0@s enator-bedfellow.mit.e du...[color=blue]
        > Syver Enstad wrote:
        >[/color]
        [color=blue]
        > You might make your life easier by having the controller and the view be
        > on the main thread and dispatch a new model to the work thread.[/color]

        Hmm. I think that makes sense, since it is the GUI that "demands"
        attention - I was doing sort-of the other way round by having a thread
        dispatching messages to models AND the GUI thread....
        [color=blue]
        > Usually you can wrap model events into gui events and let the gui's
        > mainloop sort them out and dispatch them to the controllers callbacks.[/color]

        So, To make sure that I understand correctly:

        I will have one Controller per Worker; the Controller interacts with the GUI
        and it is the Controller that "understand s" that the Worker is running in a
        separate thread and maps GUI/Worker events across the thread boundary by
        some means -

        I was planning to use of a Dispatcher/Mailbox System:

        The worker thread(S) blocks on an input queue until a message is in that
        queue - then the worker thread process the message and places a result in an
        output queue. The results in the output queue(s) of each worker are read by
        the main thread and placed in the input queues of other workers or in the
        GUI.....most of the time a worker will sleep, waiting for work.

        The input and output queues would be owned by the workers, the "distributi on
        lists" i.e. which event goes where would be owned by a "Dispatcher " running
        in the main thread .

        While this is fine for Data, setting parameters etc. is clumsy: One needs to
        setup a filter to sort parameter messages from the data and do special
        processing - i would rather keep only data in the message loop.
        [color=blue]
        > In python it is thread safe to set variables across the thread boundary,
        > the model will have to check for these variables changing though.[/color]

        ....I will need locking in the models setXyz() methods so that I do not stomp
        on some data that the worker thread is using?
        [color=blue]
        > What gui framework are you using?[/color]

        wxPython - in the hope that SciPy eventually will do a Python 2.2.3 release,
        so that by the time I need it, I can get my hands on all those neat
        Plotting, Numeric and Stats tools waiting to be liberated ;-)


        Comment

        • Brian Kelley

          #5
          Re: Design Question: GUI+Threads.

          Frithiof Andreas Jensen wrote:[color=blue]
          > Thaks for the reply,
          >
          > "Brian Kelley" <bkelley@wi.mit .edu> wrote in message
          > news:3f97ee4a$0 $573$b45e6eb0@s enator-bedfellow.mit.e du...
          >[color=green]
          >>Syver Enstad wrote:
          >>[/color]
          >
          >[color=green]
          >>You might make your life easier by having the controller and the view be
          >>on the main thread and dispatch a new model to the work thread.[/color]
          >
          >
          > Hmm. I think that makes sense, since it is the GUI that "demands"
          > attention - I was doing sort-of the other way round by having a thread
          > dispatching messages to models AND the GUI thread....
          >
          > <snip>
          > I was planning to use of a Dispatcher/Mailbox System:
          >
          > The worker thread(S) blocks on an input queue until a message is in that
          > queue - then the worker thread process the message and places a result in an
          > output queue. The results in the output queue(s) of each worker are read by
          > the main thread and placed in the input queues of other workers or in the
          > GUI.....most of the time a worker will sleep, waiting for work.[/color]

          This seems very doable. You have at least two options: 1) use a wxTimer
          to periodically tell the controller to check the worker's output queues
          or 2) have the worker send a new wxEvent to the view with the result
          data. This could be as simple as:

          wxEVT_WORKER_RE SULT = wxNewEventType( )

          def EVT_WORKER_RESU LT(win, func):
          win.Connect(-1, -1, wxEVT_WORKER_RE SULT, func)

          class WorkerResultEve nt(wxPyEvent):
          def __init__(self, result):
          wxPyEvent.__ini t__(self)
          self.SetEventTy pe(wxEVT_WORKER _RESULT)
          self.data = data

          # event wrapper so that the worker thread can send
          # results
          class EventWrapper:
          def __init__(self, window):
          self.window = window
          def setResult(self, data):
          wxPostEvent(sel f.win, WorkerResultEve nt(data))

          class WorkerThread(th read):
          def __init__(self, eventSender):
          ...
          def Run(self): ...
          ...
          self.eventSende r(result)
          self.blockForNe xtJob()

          class View:
          def __init__(self, controller,...) :
          EVT_WORKER_RESU LT(self, self.OnResult)
          def OnResult(self, evt):
          self.controller .OnResult(evt.r esult)

          A good example of this is in the wxPython thread example. Their view is
          their controller though.

          Comment

          • Frithiof Andreas Jensen

            #6
            Re: Thanks.


            "Brian Kelley" <bkelley@wi.mit .edu> wrote in message
            news:z6cmb.1830 6$Tr4.37514@att bi_s03...[color=blue]
            > Frithiof Andreas Jensen wrote:[/color]

            Thanks for the replies - I think I can come up with something now.


            Comment

            Working...