I haven’t talked about multithreading in some time but it’s even more important now than in the past. Even some laptops are coming with quad cores now so you really need to be able to take advantage of them. If you do nothing, then a computer will probably still see some better performance since several single-threaded applications can run concurrently, but if your application freezes up when it attempts to download a file or perform calculations then you’re going to look bad.
.NET 4 introduces some great parallel features. You can create tasks that perform work and provide relatively easy synchronization. They are lighter than threads since they are pooled and the API is easy. As an abstraction over tasks is Parallel LINQ extensions. You can do some amazing stuff by just adding .AsParallel() to a collection in your query. This signifies that the collection can be split across threads, with the results joined back together at the end. It’s super easy to do in most cases, and really provides a noticeable benefit. If you need to provide hints for better performance then you can, but in many cases the defaults will do just fine.
Just working with existing libraries to manipulate data across multiple threads is useful though too, as plenty of legacy code won’t have access to new extensions. Understanding and using semaphors, locks, mutexes, wait handles, and even timers is invaluable. Learn to synchronize code. You should be able to start some work, and then notify another part of your code when it should proceed.
You need to really create a solid separation of data state from presentation – in other words, your UI should query the data. State display needs to be a snapshot-in-time, not based on showing on-demand data from events. You can either periodically check your state and update the UI, or take change events and dispatch them to a UI thread (as a window message) for deferred updates. Once the window message is processed, you’ll be on the right thread and can show the new state, recent log messages, or updated status.
When a button is clicked, the event handler needs to do as little as possible. Never perform an actual action directly from the handler. Rather, start a background thread or task to do some work. When the work completes, it can notify the UI, which in turn can be dispatched to the message queue. Finally, the results can be displayed without ever causing the user to wait.
I use Picasa for photo management. The programmers made a bad assumption that file access would be instantaneous. You can never assume zero latency! Even opening a file can freeze the UI when performed in an event handler. How? Imagine if you assume that a file is 120kb (and your testing reflects this) but the user is opening an uncompressed 25MB file. What if the files are located on a network share? Assumptions will always come back to bite you. If you just assume that everything will be worst case and design your UI around that, then you’ll be fine. As soon as you decide that a “normal” environment is close to your own, then you’ll make bad choices and performance will suffer.
