in Search

cruizer

aspiring to free and open the mind of .NET developers

April 2008 - Posts

  • Lessons learned in optimising Windows forms apps

    Wow, I've been in a black hole for months!  The usual excuse -- busy at work on projects.  Now that we've gotten our app into production, we're now into firefighting, er... I mean maintenance work for that app.  Here are some of the lessons I've learned in optimising and debugging our Windows forms app:

    • Avoid overuse of threads and BackgroundWorkers
    • Application splash screens are passe but they can be a good means of hiding application load activity such as caching data and loading stuff in the background -- preferably done in parallel.  The ThreadPool works very nicely here, and users with multi-core machines immediately feel the performance benefit.
    • Most of the time, the asynchronous BeginInvoke() is much better than synchronous Invoke() when doing UI work from other threads
    • Use the System.Threading.Timer class instead of rolling my own (stupid, I know)
    • Use test-driven development as much as possible. Smile Much as I am an advocate of TDD there are times I turn into a hypocrite and cut corners. Devil Then the app grows bigger and I realise I should've walked my talk instead!
    • A great way of ensuring that our forms and controls are not riddled with dependencies is to create a separate Windows EXE project in the solution and launch the forms and controls from there -- when you do so you'll encounter lots of run-time exceptions.  Wow I didn't realise that so many of our forms and controls depended on singletons that in turn depended on services and remote calls...my bad!  It took quite a while to untangle the mess.
    • In keeping with the TDD concept of eliminating context, doing the above in conjunction with making use of the System.Diagnostics.Stopwatch class helped me find the slow portions of our code.  Imagine taking more than four seconds just to instantiate a single form?!  We were able to reduce it to around 400 milliseconds after that.  The feedback cycle was quick since I didn't have to run the entire app just to do those performance measurements. (And my boss liked those figures too, so he can present in turn to his boss, I guess.)
    • Our app forms made use of tab controls and pages, and some of our user controls made use of other controls that only appeared after certain events.  I realised that they were expensive to instantiate because the (composed) controls were already being created even though they weren't visible or active yet!  To address this, we lazy-loaded these controls only in response to certain events.  Performance radically improved after that, with only the penalty of a slight (barely noticeable, I hope) delay after the event is triggered as the composed controls are instantiated and initialised.  It was helpful to move the (initially) inactive controls to separate user controls so we still get the benefit of designer access from Visual Studio and ease of use when lazy-loading them.
    • I don't want to repeat the tips mentioned in this article, so just take a look at it.
    • ReSharper is simply indispensable.  Thank you very much, JetBrains.
    • I wish we were already using C# 3.0 on this project.  My code is littered with all those anonymous delegates. Stick out tongue
    • Perception is everything when it comes to UI.