Do I need to clean the completed tasks in tokio::task::JoinSet?

hi, I'm writing a TUI executable, I use tokio::select on crossterm::event::EventStream to achieve a non-blocking loop to receive user keyboard/mouse events.

At the same time, I also want to create an async task queue that can run some generic tasks: read/write files, update data logic, delay/timeout methods.

The word task here is similar to function pointers with a global context in C/C++.

After I read some documents, I found rust and tokio provide the tokio::task::JoinSet, it could help me create new async tasks, and run them in multiple green threads. And also possible to abort all the tasks, or wait for them done.

That's probably what I want. But I still have 1 more question:

The JoinSet is not a future Stream, so I cannot use tokio::select on it. So how could I know what task is completed?

If I don't select it, but keep create new tasks. Will it increase memory usage along with the tasks created, and finally get out of memory and crash the TUI application?

JoinSet keeps the result of running a task to completion available until you use join_all, join_next, or try_join_next to get the result of running a task. Memory usage will go up as long as this isn't done.

You have three directions you can go in:

  1. Use tokio_util::TaskTracker to track tasks. This is a lot like JoinSet, but it immediately drops the result of running a task, rather than keeping it around for later.
  2. Use tokio::select! on JoinSet::join_next as well as EventStream::next, to pull out completed tasks.
  3. Make use of futures::stream::poll_fn to turn JoinSet::poll_join_next into a stream
2 Likes

Thanks @farnz , the 2nd option seems really fit my requirement! I will have a try!

1 Like