HttpClient使用async void方法等待PostAsync挂起

时间:2013-09-26 16:19:33

标签: c# oauth windows-phone-8 async-await dotnet-httpclient

我仍然试图绕过异步,我想知道为什么以下代码导致死锁。我的用例是:我有一个服务接口,试图抽象服务的实现方式。其中一项服务是基于OAuth的Web服务。服务接口有一个方法Connect(),使用该接口的任何人都必须在使用它之前完成。

在我的客户端,我创建了我的具​​体服务对象,并在我的视图构造函数中调用Connect()(这是一个原型,所以我只是试图获得一个概念验证)。在基于OAuth的服务中,connect调用需要检索访问令牌,因此它(尝试)异步执行此操作。但是,此Connect()调用永远不会返回,并且应用程序已死锁(但UI处于活动状态)。我猜我搞砸了,试图在某个地方同步使用我的客户端,但我不确定在哪里。

控制

public class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        _webService = new OAuthBasedWebService();
        _webService.ShowAuthorizationPage += _webService_ShowAuthorizationPage; // this is defined on the concrete object -- i know, bad design
        _webService.Connect();
    }
}

基于OAuth的网络服务

public class OAuthBasedWebService()
{
    private OAuthWrapper _wrapper;

    public async void Connect()
    {
        var uri = await _wrapper.GetAuthorizationUri();
        OnShowAuthorizationPage(uri);
    }
}

internal class OAuthWrapper
{
    public async Task<Uri> GetAuthorizationUri()
    {
        var uri = await _consumer.GetAuthorizationUriAsync();
        return uri;
    }
}

internal class OAuthConsumer
{
    public async Task<Uri> GetAuthorizationUriAsync()
    {
        using (var client = new HttpClient())
        {
            client.BaseAddress = "webservicebaseaddress";
            var content = new FormUrlEncodedContent(new []
            {
                CreateParameter("oauth_consumer_key", "consumerkey"),
                CreateParameter("oauth_consumer_secret", "consumersecret")
                // etc., etc.
            });

            var response = await client.PostAsync("/method_path", content).ConfigureAwait(false);
            var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

            // parse authorization uri from responseContent
            return authorizationUri;
        }
    }
}

我知道设计需要一点工作,但我想弄清楚为什么这会死锁。我猜这是因为_webService.Connect()没有被异步调用,但我也不能await,因为它不会返回任何内容,程序的其余部分也不依赖于它。

1 个答案:

答案 0 :(得分:1)

我不确定你为什么在这里使用事件,如果问题只是因为你不能使构造函数“异步”,那么只需将conect调用移动到另一个方法:

public class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        Init();
    }

    public async void Init(){

        _webService = new OAuthBasedWebService();

        Uri uri=await _webService.Connect();
         _webService_ShowAuthorizationPage(uri);
    }
}


public class OAuthBasedWebService()
{
    private OAuthWrapper _wrapper;

    public async Task<Uri> Connect()
    {
        return await _wrapper.GetAuthorizationUri();

    }
}