"When is it a good idea to start using more than one thread?"
Usually about 9:30AM on a Monday morning, after my second cup of coffee...
Seriously...many people find this a very difficult decision.
Consider a current requirement that requires the multiplication of two (numberic) textboxes in response to a button click...
The "obvious" answer is that this is simple enough, do it inline...
Now three months later the requirement changes to take the two values submit it to a back end system (via a WebService) which may take 10+ seconds to perform the calculations and respond (we are even neglecting timeout issues).
The "obvious" answer is that this should be done on a thread.
The result may very well be a significant amount of rework to both the UI and "Business" components including architectural changes.
Since we are a small consulting firm, re-usability and flexability are factors which directly translate to our ability to provide a reliable and maintainable solution at a competitive price point.
For us, it has proven to be effective to create a UI framework that is completely decoupled form ALL of the logic. At the simplest level, the UI event handlers contain exactly 1 method call to the logic facade. The UI registers to logic facade events to update controls.
For WinForms our UI framework tests if an Invoke is required (ie the event has been fired on a different thread than the control) and transparently performs the required operation.
For ASP.Net (non-AJAX) the event handlers in the UI aggregate the data until the final event is fired, which releases a mutex on the page processing.
Other environments have similar types of constructs. This means that the logic is (almost) totally "environmentally agnostic". This has also proven to be a very effective implementation for a TDD (Test Driven Development) environment. As soon as the "logic facade" is defined, the UI (with a test logic simulator) and the Logic (with a UnitTest or other harness) can be developed completely independantly. It also allows for simple testing of conditions that may be very difficult to induce when using the entire application.
This approach is NOT for everyone, but when the development costs have been amortized over dozens of projects, the benefits really start to appear and pay of rapidly.
Getting back to the original question (no, I didnt forget it), the usage of threads (typically via the ThreadPool and WorkItems) becomes a very localized decision, where individual circumstances can be individually assessed.
What we have been finding more and more common (especially with things like the inclusion of Microsoft Windows Workflow into the application) is that the decisions regarding threading are influenced by the static hardware configuration (e.g. number of processors/cores) as well as dynamic issues (e.g. Procesor loading, IO loading, Network bandwidth).
While the thread pool does to some adaptation regarding the number of concurrent worker threads, it can not compensate for the differences between a laptop/desktop with a relatively slow single IDE drive compared to a server with high speed SCSI arrays or a SAN....
TheCPUWizard is a trademark of Dynamic Concepts Development Corp. Please visit us at www.dynconcepts.com