In this section, we are going to create an EventHandler with “green” threads or tasks, i.e. rust’s
async-await features + a future executor. We will be using tokio for this.
Here’s example code of reading key presses asynchronously comparing std::thread and tokio::task.
Notably, we are using tokio::sync::mpsc channels instead of std::sync::mpsc channels. And
because of this, receiving on a channel needs to be .await’d and hence needs to be in a async fn
method.
Even with this change, our EventHandler behaves the same way as before. In order to take advantage
of using tokio we have to use tokio::select!.
We can use tokio’s select! macro to wait on multiple
async computations and return when a any single computation completes.
Here’s what the EventHandler looks like with the select! macro:
As mentioned before, since EventHandler::next() is a async function, when we use it we have to
call .await on it. And the function that is the call site of event_handler.next().await also
needs to be an async function. In our tutorial, we are going to use the event handler in the
run() function which will now be async.
Also, now that we are getting events asynchronously, we don’t need to call
crossterm::event::poll() in the update function. Let’s make the update function take an
Event instead.
If you place the above EventHandler in a src/tui.rs file, then here’s what our application now
looks like:
Using tokio in this manner however only makes the key events asynchronous but doesn’t make the
rest of our application asynchronous yet. We will discuss that in the next section.