/**
		 * callback function that writes in_message out to the response stream
		 * of client with ID in_key.
		 */
		public void Callback( string in_message, string in_key ) {
			CallbackContext context = Callbacks[ in_key ];

			System.Diagnostics.Trace.WriteLine( "calling callback with message " + in_message );
		
			/*
			 * note that IsClientConnected doesn't get set until there has been a failure
			 * so the first time we try to write to disconnected response will result in first chance exception
			 * that we can't catch here for some reason
			 */
			if( context.Context.Response.IsClientConnected ) {
				context.Context.Response.Write( "<p>CallBack: Thread " + Thread.CurrentThread.ManagedThreadId + " " + in_message + "</p>" );
				flush( context.Context );
			}
			else {
				m_keysFlaggedForDeletion.Add( in_key );
			}
		}
		/*
		 * BeginProcessRequest gets called automatically when the request comes in
		 * We don't have to handle things in ProcessRequest/PageLoad and then set 
		 * everything up manually using RegisterAsyncTask like we do with an async
		 * aspx page. We ignore 
		 */
		public IAsyncResult BeginProcessRequest( HttpContext context, AsyncCallback callback, Object extraData ) {
			context.Response.Write( "<p>BeginProcessReqeust: Thread " + Thread.CurrentThread.ManagedThreadId + "</p>" );
			
			// async is a dummy IAsyncResult to satisfy the method signature
			AsyncOperation async = new AsyncOperation( null, null, null );

			// Callback context holds a callback and the httpcontext.
			// In hindsight we could have done this without the callback
			// so this is a possible point of refactoring. (TODO)
			CallbackContext callbackContext = new CallbackContext( 
				new NotificationCallback( Callback ), 
				context
			);

			/**
			 * TODO: this is too coarse of a lock, should be locking 'callbacks'
			 */
			lock( typeof( Register ) ) {
				Callbacks.Add( Guid.NewGuid().ToString(), callbackContext );
			}
			return async;
		}