MYOB oauthService.GetTokensAsync 未显示对话框

MYOB oauthService.GetTokensAsync not showing dialog

由于我的问题

我尝试了类似的技术来获取令牌

private t.Task<OAuthTokens> GetOAuthTokens()
    {
        var tcs = new t.TaskCompletionSource<OAuthTokens>();
        t.Task.Run(
            async () =>
            {
                var oauthService = new OAuthService(_configurationCloud);
                var code = OAuthLogin.GetAuthorizationCode(_configurationCloud);
                var response = await oauthService.GetTokensAsync(code);

                tcs.SetResult(response);
            });
        return tcs.Task;
    }

调用此使用

var task1 = GetOAuthTokens();
_oAuthKeyService.OAuthResponse = task1.Result;

但是,当我 运行 时程序锁定了。

以下作品OK

        var oauthService = new OAuthService(_configurationCloud);
        var code = OAuthLogin.GetAuthorizationCode(_configurationCloud);  // causes a login dialog
        var tokens = oauthService.GetTokens(code);
        _oAuthKeyService.OAuthResponse = tokens;

并弹出授权对话框。

当我回答你的时候 I assumed you had a requirement to use a TaskCompletionSource object so I am sorry if this has sent you in the wrong direction. As Paulo 说你通常不需要将 TaskCompletionSource 与 async/await 代码一起使用,但你确实需要更多地了解如何使用它。

调用 Result on a Task will cause that thread to block, now in a non-UI thread this isn't such an issue (just not ideal) but in a UI thread this will effectively stop your UI from responding 直到任务完成,假设它只是由于死锁而没有完全停止。

关键是要学习如何在 UI 环境中使用 async/await,因为要让它工作,你必须在任何地方都使用 async/await,否则你最终会尝试使用Task.Result 访问您的数据并获得一个被阻止的 UI 线程来解决您的麻烦。

这是一个很好的入门指南 - https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

现在我假设您正在像这样从页面中提取 code(从 GitHub 上的 code samples 拼凑而成),然后获取令牌。

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    var content = webBrowser1.DocumentText;
    var regex = new Regex(@"\<title\>(.+?)=(.+?)\</title\>");
    var match = regex.Match(content);
    if (!match.Success || match.Groups.Count != 3)
        return;

    switch (match.Groups[1].Value.ToLowerInvariant())
    {
        case "code": // we have a code
            var code = match.Groups[2].Value;
            var config = new ApiConfiguration(Configuration.ClientId, Configuration.ClientSecret, Configuration.RedirectUrl);
            var service = new OAuthService(config, new WebRequestFactory(config));
            var tokens = service.GetTokensAsync(code).Result; // <= blocking
            _keyService.OAuthResponse = tokens;
            break;

        case "error": // user probably said "no thanks"
            webBrowser1.Navigate(_logoffUri);
            break;
    }
} 

但是您的代码在 .Result

上阻塞

您需要做的就是一直使用 async/await 但是当您使用 await 时它会抱怨该方法缺少异步,因此,只需添加它;是的,这是允许的,winforms/wpf UI.

中有很多关于此的文章和博客文章

例如

// we add async to the callback - yup it's allowed 
private async void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    var content = webBrowser1.DocumentText;
    var regex = new Regex(@"\<title\>(.+?)=(.+?)\</title\>");
    var match = regex.Match(content);
    if (!match.Success || match.Groups.Count != 3)
        return;

    switch (match.Groups[1].Value.ToLowerInvariant())
    {
        case "code": // we have a code
            var code = match.Groups[2].Value;
            var config = new ApiConfiguration(Configuration.ClientId, Configuration.ClientSecret, Configuration.RedirectUrl);
            var service = new OAuthService(config, new WebRequestFactory(config));
            var tokens = await service.GetTokensAsync(code); // <= now we can use await here => non-blocking
            _keyService.OAuthResponse = tokens;
            break;

        case "error": // user probably said "no thanks"
            webBrowser1.Navigate(_logoffUri);
            break;
    }
} 

我已经uploaded the code as gist希望对你有帮助