Skip to content

Events

The library provides a way to act upon events coming from devices or connections.

In Python, the events are provided through the RxPy library. See the following example on how to subscribe to an event source.

In C#, use built-in events and delegates to interact with events from the library. See the following example on how to subscribe to an event source.

In JavaScript, the events are provided through the RxJS library. See the following example on how to subscribe to an event source.

In Java, the events are provided through the RxJava library. See the following example on how to subscribe to an event source.

Events are not available in Matlab because Matlab code cannot be executed spontaneously from other threads.

In C++, the events are provided through the RxCpp library. See the following example on how to subscribe to an event source.

connection.alert.subscribe(lambda alert: print('Alert from device:', alert))
connection.Alert += (alert) => {
    Console.WriteLine($"Alert from device: {alert}");
};
connection.alert.subscribe(alert => console.log('Alert from device:', alert))
connection.getAlert().subscribe(alert -> {
    System.out.println("Alert from device: " + alert.toString());
});
# Events are not available in Matlab because Matlab code cannot be executed spontaneously from other threads.
conn.getAlertEvent().subscribe([](const AlertEvent& alert){
    std::cout << "Alert from device: " << alert.toString() << std::endl;
});

Note that the library invokes events using a dedicated ThreadPoolExecutor. For that reason, you must use thread synchronization primitives such as concurrent.futures.Future to interact with events.

Note that the library invokes events from thread pool threads using the scheduler provided by TaskScheduler.Default. Therefore, synchronization is needed when accessing other threads. You may change the scheduler using the property EventTaskScheduler of the Zaber.Motion.Runtime.Config class. This allows, for example, using the scheduler from a WPF application to achieve synchronization with the UI thread.

Note that the library invokes events from a dedicated thread named ZaberMotionEventExecutorThread. For that reason, synchronization is needed when accessing other threads.

Note that the library invokes events from its own separate thread. For that reason, synchronization (e.g. std::mutex, std::condition_variable) is needed when accessing other threads. You should not extensively block library thread with your own code execution.

Additionally, due to the asynchronous nature of events, you must ensure that objects referenced in a subscription handler are always valid. The example below demonstrates the danger of referencing an object with a limited lifetime.

{
    Connection connection = Connection::openSerialPort("COM1");

    // handler below references connection but is invoked from another thread
    connection.getAlertEvent().subscribe([&connection](const AlertEvent& ev) {
        // using connection is not safe as it may fall out of scope
        std::cout << "Alert " << ev.toString() << " from connection " << connection.toString() << std::endl;
    });

    // other code...
}
// the connection closes as it falls out of the scope