0

I am trying to control two threads in my python code with event objects. In one thread I wait for the other thread to set the event to True and execute while it stays as 'True' and else, do something else. My problem is that the 'else' part of the loop never gets called. Any ideas why? Thank you very much in advance.

I have tried changing the 'while'statement for a 'if' statement without any luck. And I really don't know why this isn't working.

def send_thread(self):
        rospy.loginfo('set')
        self.event.set()
        for cmd in sequence:
            Do something
        rospy.sleep(2)
        rospy.loginfo('saving command in full')
        self.U_full.append(self.U_single)
        self.event.clear()
def receive_thread(self,msg):
        while self.event.wait() == True:
           Do something
        else:
           Do something else

The expected result is that the 'while' part of the recive_thread runs until the event is cleared in the sending_thread and after that, the 'else' part is executed.

  • Note: don't use `== True`. `while self.event.wait():` is *enough* to test for the boolean value here. From the documentation *This method returns true if and only if the internal flag has been set to true, either before the wait call or after the wait starts, **so it will always return True except if a timeout is given and the operation times out.*** – Martijn Pieters Jul 17 '19 at 14:13

1 Answers1

2

You are waiting on an event without a timeout, so self.event.wait() is always going to return True. From the threading.Event.wait() documentation:

This method returns true if and only if the internal flag has been set to true, either before the wait call or after the wait starts, so it will always return True except if a timeout is given and the operation times out.

Bold emphasis mine. Because it always returns true, you'll never see the else: suite executed.

Just so this is clear: the while loop will never exit if you don't use a timeout, because without a timeout, event.wait() will only return when the event flag is true. Clearing the flag with self.event.clear() sets the flag to False and so event.wait() simply won't return.

Use a timeout:

while self.event.wait(0.1):
    # do something while the event is still set
else:
    # the event has been cleared and the timeout has been reached!
    # This block can be skipped if the while block uses 'break'

Note: it is enough to test self.event.wait(). The == True part is entirely redundant. Also, a while test: ... else: ... setup only makes sense if you are going to use break in the while loop, to explicitly skip the else block. If you are not using break in the while block, you may as well remove the else: and just run the code indented in that block unconditionally.

Alternatively, test for event.is_set():

while event.is_set():
    # do something while the event is still set
else:
    # the event has been cleared and 'break' was not used

Or, invert the event, clear it at the start, and set the event only when done:

def send_thread(self):
    rospy.loginfo('set')
    self.event.clear()
    for cmd in sequence:
        Do something
    rospy.sleep(2)
    rospy.loginfo('saving command in full')
    self.U_full.append(self.U_single)
    self.event.set()

then wait for the event to be set:

if self.event.wait():
    # blocks until the event has been set by the other thread.

or if you want to do things before then, use a not self.event.wait(0.1) or simply not self.event.is_set() in your while loop.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • thank you very much for your answer. I thought that calling 'self.event.clear( )' at the end of sending_thread would set it to False again. Do you have an idea on how I could make this? – Chusikowski Jul 17 '19 at 14:22
  • @Chusikowski: yes, the flag is set to False. But `event.wait()` waits for the *opposite condition*. – Martijn Pieters Jul 17 '19 at 14:24
  • 1
    @t.m.adam: no, if no `break` is used, then the `else` is not needed here, as then the suite will be executed no matter what. I'll make that clear in the answer. – Martijn Pieters Jul 19 '19 at 13:30