Yes, I've done a lot of research on this, because my first attempt was a
miserable failure (well it worked, but it hardly produced maintainable code,
so version 2.0 is more comprehensive).
I can have well over 1000,000 rows in my database and performance outside of
the pattern (ie. on the server side with the DMBS) therefore depends on
system admin things like maintenance of indexes and hardware. This is
particularly true for me, because I'm doing a lot of work with binary
blobs - and a tree structure (ie. every row in the table has some
ancestor/descendant/sibling relationship with other records).
Inside of the pattern itself, most operations are more or less
simultaneous - ie. well within the timeframe the user might expect. For
operations that take a long time (seconds, a minute, two minutes), I have a
timer on my main form that is started when the cache handles the
Operation_Started invocation from the thread and stopped when the cache
handles the Operation_Ended invocation from the thread. After one or two
seconds, I display a progress bar. In my experience users don't mind an
operation that takes a while to complete, as long as they can see more or
less how long they have to go fetch a coffee.
Remember that from UI through Cache into Worker Thread and back to UI is
remarkably quick, ie. milliseconds - the time consuming part is database
access - and you can throw hardware at that problem to improve it. Also
because I'm using a worker thread, the UI will remain responsive.
I'm also using DataReaders/Writers, stored procedures for all data access
and the most important structure in .NET (in my opinion), the Dictionary -
so rather than having to hunt through a list of rows to find the one I'm
interested in, I can simply look the record up using a primary key. It's
worth the maintenance for the speedup you get.