/// <summary>
        /// Starts the user interface that prompts a user for a certificate.
        /// </summary>
        /// <param name="channel">The client channel.</param>
        /// <param name="callback">The callback object.</param>
        /// <param name="state">Any state data.</param>
        /// <returns>The System.IAsyncResult to use to call back when processing has completed.</returns>
        public IAsyncResult BeginDisplayInitializationUI(IClientChannel channel, AsyncCallback callback, Object state)
        {
            // Any worker thread can request a channel, so the user prompt needs to be invoked on a Single Threaded Apartment (STA) thread.  This will create that
            // thread and communicate to it the current state of the channel.
            CredentialAsyncResult credentialAsyncResult = new CredentialAsyncResult()
            {
                AsyncCallback  = callback,
                AsyncState     = state,
                Credentials    = this.Credentials,
                IClientChannel = channel
            };

            // Only single threaded apartments are allowed to call the user interface to prompt the user.  Background threads must wait until an apartment that can
            // prompt the user has validated the credentials.
            if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
            {
                // Only prompt the user once for their credentials.  After a set of credentials are chosen, they'll be used by all subsequent calls to use this
                // channel until the 'IsPrompted' flag is cleared.
                if (InteractiveChannelInitializer.IsPrompted)
                {
                    // This will prompt the user for their credentials.  It effectively creates a modal dialog box and prevents the other threads from executing,
                    // which effectively obviates the whole IAsyncResult strategy here, but this was the only way to come up with a consistent way to call the
                    // channels from the console or a Windows environment.  Note that the frame will only return control to this thread when we set the 'Continue'
                    // property to 'false'.
                    DispatcherFrame dispatcherFrame = new DispatcherFrame();
                    dispatcherFrame.Dispatcher.BeginInvoke(DispatcherPriority.Normal, this.Prompt, credentialAsyncResult);
                    dispatcherFrame.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => dispatcherFrame.Continue = false));
                    Dispatcher.PushFrame(dispatcherFrame);
                }
                else
                {
                    // If we have already prompted the user then return the credentials immediately.
                    credentialAsyncResult.Credentials = this.Credentials;
                    credentialAsyncResult.SetCompletedSynchronously();
                }
            }
            else
            {
                // The non-UI threads must wait here until a UI thread has validated the credentials.
                InteractiveChannelInitializer.ValidCredentials.WaitOne();

                // Setting the credentials in this way will make the channel act synchronously (that is, without prompting the user).  This is important after the
                // first time the channel has been initialized as we don't want to keep bother the user for credentials.
                credentialAsyncResult.Credentials = this.Credentials;
                credentialAsyncResult.SetCompletedSynchronously();
            }

            // This will be used by the caller to manage the asynchronous task that prompts the user and then invoke the EndDisplayInitializationUI with the results
            // of the dialog.
            return(credentialAsyncResult);
        }