qi.async, qi.PeriodicTask API

Introduction

qi.async() and qi.PeriodicTask allow managing concurrent tasks.

Use of these should be preferred over classic threading.Thread or threading.Timer operations.

Thread creation and destruction are low-level operations that take resources for context switching each time they happen.

Using qi operations will let the system manage the low level operations and improve its overall performance.

qi.async

Launch an operation in a concurrent task.

The qi.future returned can be used to interact with the operation. (cancel, get return value ...)

qi.async(callback [, delay=usec] [, arg1, ..., argn]) → future
Parameters:
  • callback – the callback that will be called
  • delay – an optional delay in microseconds
Returns:

a future with the return value of the function

Warning

Canceling the async operation is possible while it is delayed.

Once the callback is called, cancel will not stop it in the middle of its execution.

qi.PeriodicTask

Execute an operation periodically and asynchronously.

By default, we do not compensate the callback time. The period will be constant between the end of a call and the beginning of another.

class qi.PeriodicTask
asyncStop()

Can be called from within the callback function Request for periodic task to stop asynchronously

compensateCallbackTime(compensate)
Parameters:compensate – boolean. True to activate the compensation.

When compensation is activated, call interval will take into account call duration to maintain the period.

Warning

when the callback is longer than the period specified, compensation will result in the callback being called successively without pause

isRunning() → bool
Returns:true if task is running
isStopping() → bool
Returns:whether state is stopping or stopped.

Can be called from within the callback to know if stop() or asyncStop() was called.

setCallback(callable)
Parameters:callable – a python callable, could be a method or a function

set the callback used by the periodictask, this function can only be called once

setName(name)

Set name for debugging and tracking purpose

setUsPeriod(usPeriod)
Parameters:usPeriod – the period in microseconds

Set the call interval in microseconds. This call will wait until next callback invocation to apply the change. To apply the change immediately, use:

task.stop()
task.setUsPeriod()
task.start()
start(immediate)
Parameters:immediate – immediate if true, first schedule of the task will happen with no delay.

start the periodic task at specified period. No effect if already running

Warning

concurrent calls to start() and stop() will result in undefined behavior.

stop()

Stop the periodic task. When this function returns, the callback will not be called anymore. Can be called from within the callback function

Warning

concurrent calls to start() and stop() will result in undefined behavior.

PeriodicTask operations visualization

No compensation, task 3s, period 5s

v                                v
+-----------+                    +-----------
+  Task 3s  +      wait 5s       +  Task 3s  ...
+-----------+--------------------+-----------

Compensation, task 3s, period 5s

v                     v
+-----------+         +-----------
+  Task 3s  + wait 2s +  Task 3s  ...
+-----------+---------+-----------

Compensation, task 7s, period 5s

v                            v
+----------------------------+---------------------------+----
+         Task 7s            +         Task 7s           +  ...
+----------------------------+---------------------------+----

Examples

In the following examples, we assume we have a connected session. If you already have an application, use:

application.session.service("ALTextToSpeech")

If you don’t, then use that:

session = qi.Session()
session.connect("tcp://127.0.0.1:9559")

Doing something in 2 seconds and getting the result.

import qi

def getAnswerToLifeAndUniverse(a, b):
  return a + b

fut = qi.async(getAnswerToLifeAndUniverse, 40, 2, delay=2000000)
#do work while the result is being processed
print("Result:", fut.value())

Calling tts.say after 42 seconds.

import qi

#assume we have a connected session

tts = session.service("ALTextToSpeech")

fut = qi.async(tts.say, "42 seconds elapsed", delay=42000000)

#wait for the sentence to be said
fut.wait()

Calling tts.say every 10 seconds.

import qi
import time
import functools

#assume we have a connected session

tts = session.service("ALTextToSpeech")
sayHelloCallable = functools.partial(tts.say, "hello")

sayHelloTask = qi.PeriodicTask()
sayHelloTask.setCallback(sayHelloCallable)
sayHelloTask.setUsPeriod(10000000)
sayHelloTask.start(True)

time.sleep(30)
sayHelloTask.stop()

Canceling a delayed operation before its execution.

import qi
import time

def dummyAction():
  # do your operations here
  qi.info("async example", "My dummy action is over")

action = qi.async(dummyAction, delay=15000000)
time.sleep(5)
action.cancel()
action.wait()
if action.isCanceled():
  qi.info("async example", "dummyAction was canceled as expected")