I had a directory full of images to scale and a progress dialog that froze while doing it. The obvious fix was a worker thread. The less obvious consequence was a new class, a queue, two mutexes and several opportunities to close the dialog at exactly the wrong moment.

Qt 4.4 includes QtConcurrent, which handles this sort of bounded parallel work at a higher level. Instead of managing threads, I can express the operation as a function over a sequence and let mapped() apply it. The result is represented by a QFuture, and QFutureWatcher turns progress and completion into signals suitable for the event-driven parts of the application.

The thread pool is the useful mechanism here. Creating one thread per thumbnail would merely exchange a frozen interface for a small scheduling experiment. QtConcurrent uses a pool and distributes work across it. The application says what can run independently; the library decides which worker executes each item.

There are several forms. run() is convenient for one function call. mapped() transforms each input into an output, while filtered() selects items. The blocking variants are tempting in a command-line program but defeat the point in a GUI thread. I use a watcher and return to the event loop.

This does not make shared state safe. The mapping function must not casually update widgets, append to an unprotected container or rely on execution order. GUI objects remain in their own thread. I pass immutable input into the workers and collect results through the future. If work needs elaborate communication or a long-lived thread with its own event loop, QThread is still the clearer tool.

Cancellation is another qualified promise. A future can request cancellation, but code already running does not vanish. The operation must reach places where cancellation can take effect. For tiny image conversions this is acceptable; for one enormous function it may not be.

I prefer QtConcurrent when the problem really is a collection of independent jobs. It removes thread bookkeeping without hiding that concurrency exists. That is a narrower claim than “threads made easy,” and therefore more believable. My thumbnail dialog now moves smoothly, and the implementation lost enough plumbing that I can almost understand code I wrote last week.