我有一个Windows Phone 8应用程序,在其中我正在呼叫HttpClient.PostAsync,并且它从不返回结果。它只是坐在那里并挂起。如果我从控制台应用程序运行完全相同的代码,它将几乎立即返回结果。完成工作的所有代码都驻留在可移植的类库中。如果您能提供任何帮助,我们将不胜感激。我已经在此状态下找到的所有其他问题都使用await client.PostAsync。

我的类库中的代码是这样的:

public class Authenticator
{
    private const string ApiBaseUrl = "http://api.fitbit.com";
    private const string Callback = "http://myCallbackUrlHere";
    private const string SignatureMethod = "HMAC-SHA1";
    private const string OauthVersion = "1.0";
    private const string ConsumerKey = "myConsumerKey";
    private const string ConsumerSecret = "myConsumerSecret";
    private const string RequestTokenUrl = "http://api.fitbit.com/oauth/request_token";
    private const string AccessTokenUrl = "http://api.fitbit.com/oauth/access_token";
    private const string AuthorizeUrl = "http://www.fitbit.com/oauth/authorize";
    private string requestToken;
    private string requestTokenSecret;

    public string GetAuthUrlToken()
    {
        return GenerateAuthUrlToken().Result;
    }

    private async Task<string> GenerateAuthUrlToken()
    {
        var httpClient = new HttpClient { BaseAddress = new Uri(ApiBaseUrl) };
        var timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0);
        var oauthTimestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString(CultureInfo.InvariantCulture);
        var oauthNonce = DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture);

        var authHeaderValue = string.Format(
            "oauth_callback=\"{0}\",oauth_consumer_key=\"{1}\",oauth_nonce=\"{2}\"," +
            "oauth_signature=\"{3}\",oauth_signature_method=\"{4}\"," +
            "oauth_timestamp=\"{5}\",oauth_version=\"{6}\"",
            Uri.EscapeDataString(Callback),
            Uri.EscapeDataString(ConsumerKey),
            Uri.EscapeDataString(oauthNonce),
            Uri.EscapeDataString(this.CreateSignature(RequestTokenUrl, oauthNonce, oauthTimestamp, Callback)),
            Uri.EscapeDataString(SignatureMethod),
            Uri.EscapeDataString(oauthTimestamp),
            Uri.EscapeDataString(OauthVersion));

        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
            "OAuth",
            authHeaderValue);

        var content = new StringContent(string.Empty);
        var response = await httpClient.PostAsync(RequestTokenUrl, content);

        if (response.StatusCode != HttpStatusCode.OK)
        {
            throw new Exception("Request Token Step Failed");
        }

        var responseContent = await response.Content.ReadAsStringAsync();
        var responseItems = responseContent.Split(new[] { '&' });

        this.requestToken = responseItems[0];
        this.requestTokenSecret = responseItems[1];

        var url = string.Format("{0}?{1}&display=touch", AuthorizeUrl, this.requestToken);

        return url;
    }

    public string CreateSignature(string url, string nonce, string timestamp, string callback)
    {
        // code removed
        return signatureString;
    }

    private static byte[] StringToAscii(string s)
    {
        // code removed
        return retval;
    }
}


我有一个调用此库的控制台应用程序,它可以正常运行:

public class Program
{
    public static void Main(string[] args)
    {
        var o = new Program();
        o.LinkToFitbit();
    }

    public void LinkToFitbit()
    {
        var authenticator = new Authenticator();

        // this works and returns the url immediately
        var url = authenticator.GetAuthUrlToken();

        // code removed
    }
}


当我从WP8应用程序运行时,到达库中的这一行时,它只是挂起:

var response = await httpClient.PostAsync(RequestTokenUrl, content);


这是我的WP8代码:

public partial class FitbitConnector : PhoneApplicationPage
{
    public FitbitConnector()
    {
        InitializeComponent();
        this.AuthenticateUser();
    }

    private void AuthenticateUser()
    {
        var authenticator = new Authenticator();
        var url = authenticator.GetAuthUrlToken();

        // code removed
    }
}

最佳答案

此行阻塞了UI线程:

public string GetAuthUrlToken()
{
    return GenerateAuthUrlToken().Result;
}


await httpClient.PostAsync()之后的代码需要在UI线程中执行,但由于被阻止而无法执行。

因此,替换为:

private void AuthenticateUser()
{
    var authenticator = new Authenticator();
    var url = authenticator.GetAuthUrlToken();

    // code removed
}


有了这个:

private async void AuthenticateUser()
{
    var authenticator = new Authenticator();
    var url = await authenticator.GenerateAuthUrlToken();

    // code removed
}


注意,我正在使用asyncawait。您将需要公开GenerateAuthUrlToken()。您可以删除GetAuthUrlToken()

简而言之,Task<T>.Result不是异步的。

关于c# - WP8 HttpClient.PostAsync永远不会返回结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20734575/

10-10 00:04