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)..."

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 posted last week for external tests. Some users reportedstrange 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). Have a look to the constructor of the class we used for background thread result processing:

As you can see in line 10 we used the System.Timers.Timer class. The syncObject parameter is (as you can guess) the main form.

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! Here is the implementation:

As you can see: no real magic things happen. Interesting is the line 22: if there are no queued results, we just return and do nothing. But there was already a cost calling it in sync with the main UI thread, look at the call chain above! And as such it breaks the UI thread every 250 msecs also if there is just nothing to do.

But lets look what will happen if there is a result to process: let's pick the call into owner.OnUpdatedFeed(). The owner forwards to the UI class and no .InvokeRequired call is needed (the only good thing so far). It calls into FeedTreeNodeBase class to update the unread counter and node text of the treeview that in turn calls the TreeNode::UpdateNode() function. It will call into the treeview:WndProc(m), WmNotify(), CustomDraw()..., FontHandleWrapper::.ctor,... Font::ToHFont(), Font:ToLogFont() and...? You are right: it checks the code access security with CodeAccessPermission::Demand()! Right and secure, but slow. More slow even though the CodeAccessSecurityEngine::Check calls into a AppDomain::MarshalObject(Object) followed by a parameter memory serialization into another AppDomain! I scratched my head: what the f...? Then I remembered the second quote (above): Ticks are generated out of process! So this was the obvious reason for the cross-AppDomain call (memory allocation: 75MB, 33%).

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! Be careful, there are also other issues with it I did not mentioned here, read the docs!
Now I'm off to close related bugs...