In my view, you should not synchronously update a view when the underlying model changes, especially not Each and Every time.
The VirtualTreeView is a visual control. Human beings do not need to see the tree update in real time, any more than 3x per second is wasted. So don't do it.
Instead, update your model (objects, classes), set a notification flag, and then (from a TTimer), do an asynchronous SINGLE update of VirtualStringTree.RootNodeCount, that occurs 3x per second maximum. (More than one setting of this update flag each 333 msec leads to a minimum waiting period of 333 msec until it actually updates.) That's my arbitrary user-interface "faster than this and it's just flicker and churn, and no use whatsoever" constant.
Delphi's own developers ran into this with VirtualTreeView, I know because I logged the QC bug involved. If you did enough "OutputDebugString" messages in Delphi 2009, the IDE would become non-responsive. Why? Because they did what you're doing. Don't do it. I'm not saying that a user click should cause a 333 ms wait before the screen refreshes. I'm saying that some process that is generating tree content continuously should only notify the tree's "view controller" of changes 3 times per second, maximum.