WP8 HttpClient.PostAsync永远不会返回结果 [英] WP8 HttpClient.PostAsync never returns result

查看:96
本文介绍了WP8 HttpClient.PostAsync永远不会返回结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a Windows Phone 8 app where I am calling await HttpClient.PostAsync and it never returns a result. It just sits there and hangs. If I run the exact same code from a console app, it returns the result almost immediately. All of the code doing the work resides in a portable class library. I would appreciate any help you may be able to give. All of the other issues I have found on this state to use await client.PostAsync, which I am already doing.

我的类库中的代码如下:

The code in my class library is as such:

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;
    }
}

我有一个控制台应用程序,它会调用此库可以正常工作:

I have a console app that calls this library and it works with no problem:

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应用程序运行时,到达库中的这一行时,它只是挂起:

When I run from my WP8 app, it just hangs when it gets to this line in the library:

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;
}

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

The code after the await httpClient.PostAsync() needs to be executed in the UI thread, but it can't be executed because is is blocked.

因此,替换为:

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
}

我正在使用异步等待。您将需要公开 GenerateAuthUrlToken()。您可以擦除 GetAuthUrlToken()

Notice I am using async and await. You will need to make GenerateAuthUrlToken() public. You can erase GetAuthUrlToken().

简而言之,就是 Task< T>。结果不是异步的。

In few words, Task<T>.Result is not asynchronous.

这篇关于WP8 HttpClient.PostAsync永远不会返回结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆