In C++, you'd stack-allocate an object representing a spinner, that spawns said spinner in its constructor, and deletes it in its destructor. Then the spinner doesn't outlive the processing code, no matter what path execution took to end the processing.
There are similar patterns in GC-enabled languages ("with" idiom). Async does throw a wrench into this a bit, though.