I've been in the process of moving apartments so I haven't had free time to work on RSS Bandit. In the meantime, we've been getting lots of excellent bug reports from people using the alpha version of the Nightcrawler release. One of the bug reports we've gotten was that somewhere along the line we introduced a bug that caused significant memory consumption (hundreds of megabytes). Since I've been busy, Torsten tracked it down and wrote about it in his post More to Know About .NET Timers. He wrote

As you may know, .NET 1.1 supports three different Timer classes:

  1. Windows timers with the System.Windows.Forms.Timer class
  2. Periodical delegate calling with System.Threading.Timer class
  3. Exact timing with the System.Timers.Timer class

The timings are more or less accurate (see CodeProject: Multithreading in .NET), but that is not the point I want to highlight today. Two sentences from the mentioned codeproject article are important for this post:

"... Events raised from the windows forms timer go through the message pump (together with all mouse events and UI update messages)..."

and

"...the System.Timers.Timer class. It represents server-based timer ticks for maximum accuracy. Ticks are generated outside of our process..."

To report state and newly retrieved items from requested feeds we used a concept to serialize the asynchronous received results from background threads with the help of a timer. This was introduced in the NightCrawler Alpha Dare Obasanjo posted last week for external tests. Some users reported strange failures, memory hog up and bad UI behavior with this Alpha so I would suggest here to not use it anymore for testing if your subscribed feeds count is higher than 20 or 30 feeds.

The idea was not as bad as it seems to be (if you only look at the issues above). The real issue in our case was to use simply the wrong timer class! The UI state refresh includes an update of the unread counters that is reported to the user within the treeview as number postfixes and (more important here) a font refresh (as user decides, default is to mark the feed caption text bold).
...

So what happens exactly now if the timer fires? I used the CLR Profiler to get the following exiting results. The event is called in sync. with the SynchronizingObject, means Control::WndProc(m) calls calls into System.Windows.Forms.Control::InvokeMarshaledCallbacks void(), MulticastDelegate::DynamicInvokeImpl()... and then our event method OnProcessResultElapsed(). The allocation graph mentions 101 MB (44.78%) used here!
...

So what to do to fix the problem(s)? Simply use the Windows.Forms.Timer! Think about it: it is driven by the main window message pump and runs always in the right context of the main UI thread (no .InvokeRequired calls). Timing isn't an important point here, we just want to process one result each time we are called. Further: no cross-AppDomain security check should happen anymore! With that timer it is just a simple update control(s) with some fresh data!

So take care of the timer class(es) you may use in your projects! Check their implications!

Tracking down bugs is probably the most satisfying and yet frustrating things about programming. I'm glad we got to the root of this problem.

By the way, don't forget to cast your vote in the RSS Bandit Logo Design contest. The time has come for us to update the imagery related the application and we thought it'd be great t have both the new logo and the decision on what it should be in the hands of our users.