I have always used pipe, Storable, fork, and Tk's fileevent mechanism for passing results back to a GUI task from various worker tasks. The tricky bit is that you need two "uplink" pipes: one in nonblocking mode that you can give to Tk and read short text reports, and one in blocking mode that you can use with Storable to pass results back from workers. Pipes work even within the same process, so you should be able to easily do something similar with threads. (With forked children and Tk, you must also take care that the children call CORE::exit rather than Tk::exit, which will cause the parent to exit. If you value your sanity, the forked children do not touch the UI.)