我仍在尝试围绕异步进行思考,我想知道为什么以下代码会导致死锁。我的用例是这样的:我有一个服务接口,它试图抽象出服务是如何实现的。其中一项服务是基于 OAuth 的 Web 服务。服务接口有一个方法Connect()
,任何使用该接口的人都必须在使用它之前执行该方法。
在我的客户端,我创建了具体的服务对象并调用Connect()
了我的视图构造函数(这是一个原型,所以我只是想获得一个概念证明)。在基于 OAuth 的服务中,连接调用需要检索访问令牌,因此它(尝试)异步执行此操作。但是,此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
做,因为它不返回任何东西,程序的其余部分也不依赖它。