On 30Mar2017 12:40, Alexandru Achim <achim_alexan...@yahoo.com> wrote:
Dear users,
I had a problem regarding Threads in python and Gtk3. I want to stop a while 
loop in Gtk , a loop starded with a thread.
I want to control a delay timer laser board with give me ,when I send a command 
by serial connection, give back continuous status values ; but I want to stop 
this loop , to modify parameters and start the loop again.

A part of my code is here :
import serial
import threading
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GObject,Pango, GLib
from threading import Thread
GObject.threads_init().............
#START BUTTON

    def start(self,button_start):
       Thread(target=self.start_on,args=(self.button_start))

You don't seem to start the Thread here.

    def start_on(self,widget,data=None):
    if ser.isOpen():
        cmd = 's'   
        ser.write(cmd.encode('ascii')+'\r\n')
        while True:
            try:
                 values = ser.readline()
                 self.label_result.set_text(values)
            except:
                      pass
       
#STOP BUTTON        
    def stop(self,button_stop):
     Thread(target=self.stops,args=(button_stop)).start()
       
    def stops(self,widget,data=None):
    if ser.isOpen():
        try:  
            cmd = 'f'   
            ser.write(cmd.encode('ascii')+'\r\n')
            status = ser.readline()
            self.label_result.set_text(status)
        except:
            pass
...........win=sincrolaser()
win.show_all()
Gtk.main()

But the problem is when I send STOP button program freeze , probably the loop 
from the start is looping forever. How do I stop the start thread?
Is there a posibility to give a thread flag or identity to find him and close?

It is easy enough to keep the identities of threads. Example:

 def start(self, button,start):
   self.start_thread = Thread(target=.......)
   self.start_thread.start()

But to stop a thread you pretty much need to set a flag and have the thread check it periodicly. Example:

 def start(self, button,start):
   self.start_thread = Thread(target=.......)
   self.start_run = True
   self.start_thread.start()

 def start_one(self, widget, data=None):
   ...
   while self.start_run:
     try:
       ...

and to stop it one goes:

 self.start_run = False

Next time around the loop the thread checks the flag and quits the while loop.

Another concern I have with your code is that nothing prevents _both_ the stop and start threads from running at the same time. I Imagine that calling ser.readline from two threads at once leads to unpredictable and possible insane behaviour. And having both threads writing to the serial line at one may write nonsense to the other end, etc.

I recommand you take a mutex around your worker threads, so that only one can be active at once. Example:

 from threading import Lock

 # wherever your setup stuff happens; you need to allocate the Lock
 def __init__(self, ...):
   self.ser_lock = Lock()

 def start_one(self, widget, data=None):
   with self.ser_lock:
     ...
     while start_run:
       try:
         ..

and likewise in stops:

 def stop(self,button_stop):
   self.start_run = False    # ask "start" tyhread to terminate
   self.stop_thread = Thread(target=self.stops,args=(button_stop))
   self.stop_thread.start()

 def stops(self,widget,data=None):
   with self.ser_lock:
     if ser.isOpen():
       try:  
         ...

You can see that neither thread will try to user the serial device until it holds the lock, avoiding conflict. The stop button active sets the "start_run" flag variable to False, causing the start thread to exit when it notices.

Hopefully this will give you more control over your program's behaviour. A few helpful print() calls scattered throughout should show you what is going on, too.

Note that it would also be prudent to prevent more than one start thread running, and so forth.

Cheers,
Cameron Simpson <c...@zip.com.au>
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to