+2  A: 

As I read your description, I thought of 2 things: Asynchrony and Caching.

First, Asynchrony

Why would you block for 0.5s? Why not use an ajax call, and in the callback, update the page with the retrieved info. There is no blocking for a set time, it is done asynchronously. You'd have to suppress multiple clicks though, while a request is outstanding, but that shouldn't be a problem at all.

You can also pre-load the in-page cache in the background, using setInterval or better, setTimeout. Especially makes sense if the cost to compute or generate the calendar is long and the data size is relatively small - in other words, small enough to store months in the in-page cache even if it is never used. Sounds like you may be doing this anyway and only need to block when the user jumps out of the range of cached data.

Intelligent Caching

I am imagining the callback function - the one that is called when the ajax call completes - will check if the currently selected date is on the "edge" of the cached data - either the first week in cache or the last week (or whatever). If the user is on the edge, then the callback can send out an additional request to optimistically pre-load the cache up to the 4 week limit, or whatever time range makes sense for your 80% use cases.

You may also consider caching the generated calendar data on the server side, on a per-user basis. If it is CPU- and time-intensive to generate these things, then it should be a good trade to generate once and keep it in the server-side cache, invalidating only when the user makes an update. With x64 servers and cheap memory, this is probably very feasible. Depending on the use cases, it may make for a much more usable interaction, the 2nd time a user connects to the app. You could even consider pre-loading the server-side cache on a per-user basis, before the user requests any calendar.

Cheeso
Asynchrony: Yep, I'm actually using the callbacks from the page methods to re-call the caching, it seems to work ok. I'm blocking using an UpdatePanel as it's easier to ensure the user cannot click on anything while the request posts, and guarantees a quick turnaround for that week. As for intelligent caching, it is hard to deal with the situation of the user trying to naviagate to a particular week by clicking on the 'next' button repeatedly, as there's not quite enough time to do the check and get the data back.
Ed Woodcock
As for Server-side caching, it's not really feasible in a group environment, it's quite possible to have another user change their appointments while they're logged off, or even while they're logged on. If it's pure client-side, they get refreshed when they load the page again, which ensures the data will always be reasonably fresh.
Ed Woodcock
About the "not enough time" problem. . . There are ways to handle it intelligently. One way is to introduce a delay, via setTimeout, between the click and the resulting ajax call. If an additional click happens before the delay expires, then reset the timer and wait some more. You can assume that multiple Next clicks will occur within 650ms of each other (for example), so if you get three clicks in a row, followed by a delay of more than 650ms, you know to request 3 weeks hence, rather than "this week", "next week" and "the week following" with 3 separate ajax calls.
Cheeso
I disagree it's not feasible in a group environment. You're looking for a distributed memory cache (DMC) look at Memcache, Velocity and similar. At point where you've reached scalability issues and you have a load balanced environment your next step should always be a DMC system after you've verified through profiling that you've reasonably made all the performance increases possible from code execution.
Chris Marisic
I agree with Marisic; there's no logistical obstacle to prevent you from using server-side caching. A distributed memory cache will scale well across a farm. Also, you can do cache validation checks before using the contents of the cache, to avoid the problem where the backing store has been changed by a different application. On the other hand, I understand that it might not be practical for you to do this.
Cheeso