/// <summary>
        /// The async implementation of <see cref="GetRequestToken"/>
        /// </summary>
        public static void GetRequestTokenAsync(AsyncCallback<OAuthRequestToken> callback)
        {
            var requester = new TokenObtainRequest(APIUri.RequestToken);

            requester.RequestAsync(delegate(AsyncCallResult<string> result)
            {
                var asyncResult = new AsyncCallResult<OAuthRequestToken>();
                asyncResult.Success = result.Success;
                asyncResult.Exception = result.Exception;
                if (result.Success)
                {
                    // Processes response.
                    var match = Regex.Match(result.Data, Constants.RetrieveRequestTokenPattern, RegexOptions.IgnoreCase);
                    if (!match.Success)
                        throw new AMicroblogException(LocalErrorCode.UnknowError, "Failed to retrieve request token from the web response.");

                    var requestToken = match.Groups[1].Value;
                    var requestTokenSecret = match.Groups[2].Value;

                    asyncResult.Data = new OAuthRequestToken() { Token = match.Groups[1].Value, Secret = match.Groups[2].Value };
                }
                else
                    callback(asyncResult);
            });
        }
        /// <summary>
        /// The async implementation of <see cref="GetAccessToken"/>
        /// </summary>
        public static void GetAccessTokenAsync(AsyncCallback<OAuthAccessToken> callback, OAuthRequestToken requestToken, string verifier)
        {
            ValidateArgument(requestToken, "requestToken");
            ValidateArgument(requestToken.Token, "requestToken.Token");
            ValidateArgument(requestToken.Secret, "requestToken.Secret");
            ValidateArgument(verifier, "verifier");
            // If the required auth header item is not given (for example: an incorrect name is used.), server will not response.
            var requester = new TokenObtainRequest(APIUri.AccessToken);
            requester.Params.Add(new ParamPair(Constants.OAuthToken, requestToken.Token));
            requester.Params.Add(new ParamPair(Constants.OAuthVerifier, verifier));
            requester.Secret = requestToken.Secret;
            requester.RequestAsync(delegate(AsyncCallResult<string> result)
            {
                var asyncResult = new AsyncCallResult<OAuthAccessToken>();
                asyncResult.Success = result.Success;
                asyncResult.Exception = result.Exception;
                if (result.Success)
                {
                    var accessTokenMatch = Regex.Match(result.Data, Constants.RetrieveAccessTokenPattern, RegexOptions.IgnoreCase);
                    if (!accessTokenMatch.Success)
                        throw new AMicroblogException(LocalErrorCode.UnknowError, "Failed to retrieve access token.");

                    var accessToken = accessTokenMatch.Groups[1].Value;
                    var accessTokenSecret = accessTokenMatch.Groups[2].Value;
                    var userID = accessTokenMatch.Groups[4].Value;

                    asyncResult.Data = new OAuthAccessToken() { Token = accessToken, Secret = accessTokenSecret, UserID = userID };
                }
                else
                    callback(asyncResult);
            });
        }