2015-09-03 52 views
0

由於我的問題的結果about TaskCompletionSourceMYOB oauthService.GetTokensAsync沒有顯示對話框

我嘗試了類似的技術用於獲取令牌

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; 

,並提出了授權對話框。

+0

@shaun_a_wilde請你能幫忙嗎? –

+0

什麼UI?如果它是基於WinForms或WPF的消息泵,則會阻止它。你爲什麼使用'Task.Run'和'TaskCompletionSource'來調用已經異步的代碼? –

+0

我編輯了這個問題,以澄清它是鎖定的程序而不是UI。 (我必須按Ctrl Alt Delete結束程序)。我正在使用Task.Run和TaskCompletionSource以等待任務運行。有一個同步選項.GetTokens,但我正在嘗試。 –

回答

4

當我回答你的previous question我假設你有一個使用TaskCompletionSource對象的需求,所以我很抱歉,如果這使你發現了錯誤的方向。正如Paulo曾經說過,你通常不需要使用TaskCompletionSource和async/await代碼,但你需要更多地瞭解如何使用它。

在任務上調用Result會導致該線程阻塞,現在在非UI線程中,這不是這樣的問題(只是不理想),但在UI線程中,這將有效地阻止您的UI from responding,直到任務假設它只是因爲僵局而沒有完全停止。

事情是要學習如何在UI環境中使用異步/等待,因爲要使它工作,你也必須使用異步/等待處處,否則最終會嘗試使用Task.Result來訪問數據並獲取一個阻塞的UI線程爲您的麻煩。

這是一個很好的入門指南 - https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

現在假設你從這樣的頁面(從code samples在GitHub上的鵝卵石)拉動code然後取令牌。

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

你需要做的,當你使用等待它抱怨的方法缺乏異步的是使用異步/ AWAIT一路上揚但什麼,所以,只需添加它;是的,這是允許的,並且有許多關於這個的文章和博客文章catch people new to async/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我希望它能幫助

+0

謝謝肖恩。 我得到以下塊: VAR令牌= service.GetTokensAsync(代碼)。結果; 我得到,我可以使用service.GetTokens()來代替,這也將阻止。 我不明白爲什麼當我使用service.GetTokens()時,登錄對話框纔會出現。當我使用Async選項時,程序鎖定並從不解鎖。就好像登錄對話框是不可見的。 –

+2

@kirsteng - 與小片段提供的是很難說 - GetTokens實現[可](https://github.com/MYOB-Technology/AccountRight_Live_API_.Net_SDK/blob/master/MYOB.API.SDK/SDK/ Services/OAuthService.cs#L64)實際上使用了一種不依賴於異步/等待模式的替代異步方法 - 因此它可以用於沒有異步/等待的框架版本,例如.NET2。 –

+0

謝謝肖恩,我現在只打算使用非異步版本的GetTokens()。 –