Other Solutions to the Join Problem
The approach in the previous example solves the join problem, but the implementation is confusing because:
It relies on a constructor to initiate the operation, instead of using a regular function call.
It requires a separate class for each asynchronous operation.
A better way to solve the problem is to move the initiation of the asynchronous operation to a public member function of the class. In this case, the operation is started by calling the member function, which creates a threaded runnable to perform the actual operation. A handle to that runnable could be stored within the class so that a join can be performed when the object is destroyed.
Other problems are created, however, if the service is invoked a second time:
If the function does not wait on the previous operation, but instead creates another thread, then it needs to store a handle to the second thread object.
If the function stores the handle in the internal handle member, the reference to the first runnable is lost.
To avoid these new problems:
Keep any thread creation in the active object constructor.
Add member functions that delegate any service requests to those thread or threads that are created.