How to create a infinitely running State Machine in a thread behind the GUI.

Hi,

I’m new to python and wxpython so need some help choosing the architecture.

Bascially i have

  1. A GUI which should indicate status , currently i’m just using a wxBUTTON and it’s label() and backgroundColor() methods to update the status.

  2. The status button shows ‘START’ and when the user presses the start button proceed to (3)

3.3.0 change the status button to ‘SELECT Type …’

3.1 open a dialog box to ask for the type of device(which is a dialog box with buttons) and when user selects one of the dialog box proceed to (4)

4.4.0 change the status button to ‘SCANNING COM…’

4.1 I have to read a COM port which has a timeout of 5 secs and

4.2 check if proper data was read if not then change the status button to 'RE-SCAN code ’ and repeat the read (4.1) again from the COM port else proceed to (5)

5.5.0 change the status button to ‘DECODING Received Data…’

5.1 Perform some task on the properly received data from (4) and proceed to (6)

6.6.0 proceed to (3)

The user will be able to quit the loop anytime using a abort button in the GUI.

In short,

1.keep running the state machine in the thread in infinite loop and send events to GUI

2.update the GUI status button on receiving the events from state machine inside thread

3.update the state machine’s state from the GUI as GUI has to wait for user selection in the DialogBox buttons.

Putting the above statechart using wx.EVT_IDLE was very unresponsive as COM port reading was holding up the gui task

So in-order to make the GUI more responsive i have chosen to make the Task (3) to (6) in a separate thread.

and i’m facing problem with the sync between the events flowing from thread->GUI.

There should be some way to lock the state_machine running in the thread until the GUI has done some specific task say Dialog box pop up and user accepted a button in step(3.0,3.1)

the ShowModal() doesn’t seem to work as the thread would put another event which would trigger another another same Dialog box.

I’m totally confused with synchronising …!

Vin wrote:

I'm new to python and wxpython so need some help choosing the
architecture.
Bascially i have
1. A GUI which should indicate status , currently i'm just using a
wxBUTTON and it's label() and backgroundColor() methods to update the
status.
2. The status button shows 'START' and when the user presses the start
button proceed to (3)
3.3.0 change the status button to 'SELECT Type ...'
   3.1 open a dialog box to ask for the type of device(which is a
dialog box with buttons) and when user selects one of the dialog box
proceed to (4)
4.4.0 change the status button to 'SCANNING COM...'
   4.1 I have to read a COM port which has a timeout of 5 secs and
   4.2 check if proper data was read if not then change the status
button to 'RE-SCAN code ' and repeat the read (4.1) again from the COM
port else proceed to (5)
5.5.0 change the status button to 'DECODING Received Data...'
   5.1 Perform some task on the properly received data from (4) and
proceed to (6)
6.6.0 proceed to (3)
....
The user will be able to quit the loop anytime using a abort button in
the GUI.
...
I'm totally confused with synchronising ...!

You have two challenges here: how to signal from the GUI to the worker,
and how to signal from the worker to the GUI.

If the worker thread is part of the GUI class, then the only issue is
making sure you don't touch GUI things from outside the main thread.
The easiest way to handle that is to use wx.CallAfter. When the COM
thread has information to return, do a wx.CallAfter and pass the string
or buffer that was read.

For the other direction, you might consider making each of the
asynchronous steps as narrow as possible. For example, in step 4, use a
thread to go read the COM port. Have that thread us wx.CallAfter to get
back to the main thread to examine the data. Then, have the COM port
thread exit. It's job is done. If you need to read the COM port again,
you just spin up another thread to do it. Thread startup time is
trivial compared to the wait for a COM port.

Implementing the "Cancel" button can be a little tricky. How are you
doing the COM port timeout? If you are just doing a blocking read, then
you can't cancel it. If you are checking for status in a loop, then you
can. However, just because you can't cancel the read doesn't mean you
can't make it LOOK like it was cancelable. You can just let the read
time out, and set a flag that tells the data handler to ignore whatever
it got back.

By doing that, you no longer have to worry about administering a
long-running thread. You just have a series of short-running threads
handling tasks in nice, bite-sized chunks.

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

The GUI basically is a state machine behind the scenes. I don’t think you want to use EVT_IDLE, as I think that is when the GUI is drawn, or it is close to when that happens.

Look at the threading.Event class, also the Queue class

https://docs.python.org/2/library/threading.html#event-objects

https://docs.python.org/2/library/queue.html

If you don’t want to use a timeout for your COM port, I suggest looking at the multiprocessing module, which is basically a drop-in replacement for the threading module.

https://docs.python.org/2/library/multiprocessing.html

···

On Wednesday, July 30, 2014 5:01:15 PM UTC-7, Vin wrote:

Hi,

I’m new to python and wxpython so need some help choosing the architecture.

Bascially i have

  1. A GUI which should indicate status , currently i’m just using a wxBUTTON and it’s label() and backgroundColor() methods to update the status.
  1. The status button shows ‘START’ and when the user presses the start button proceed to (3)

3.3.0 change the status button to ‘SELECT Type …’

3.1 open a dialog box to ask for the type of device(which is a dialog box with buttons) and when user selects one of the dialog box proceed to (4)

4.4.0 change the status button to ‘SCANNING COM…’

4.1 I have to read a COM port which has a timeout of 5 secs and

4.2 check if proper data was read if not then change the status button to 'RE-SCAN code ’ and repeat the read (4.1) again from the COM port else proceed to (5)

5.5.0 change the status button to ‘DECODING Received Data…’

5.1 Perform some task on the properly received data from (4) and proceed to (6)

6.6.0 proceed to (3)

The user will be able to quit the loop anytime using a abort button in the GUI.

In short,

1.keep running the state machine in the thread in infinite loop and send events to GUI

2.update the GUI status button on receiving the events from state machine inside thread

3.update the state machine’s state from the GUI as GUI has to wait for user selection in the DialogBox buttons.

Putting the above statechart using wx.EVT_IDLE was very unresponsive as COM port reading was holding up the gui task

So in-order to make the GUI more responsive i have chosen to make the Task (3) to (6) in a separate thread.

and i’m facing problem with the sync between the events flowing from thread->GUI.

There should be some way to lock the state_machine running in the thread until the GUI has done some specific task say Dialog box pop up and user accepted a button in step(3.0,3.1)

the ShowModal() doesn’t seem to work as the thread would put another event which would trigger another another same Dialog box.

I’m totally confused with synchronising …!