@@ -63,6 +63,11 @@ public class WindowsProvider : BaseProvider
6363 /// </summary>
6464 public WebAccountProviderConfig WebAccountProviderConfig => _webAccountProviderConfig ;
6565
66+ /// <summary>
67+ /// Gets or sets which DispatcherQueue is used to dispatch UI updates.
68+ /// </summary>
69+ public DispatcherQueue DispatcherQueue { get ; set ; }
70+
6671 /// <summary>
6772 /// Gets a cache of important values for the signed in user.
6873 /// </summary>
@@ -71,7 +76,7 @@ public class WindowsProvider : BaseProvider
7176 private readonly string [ ] _scopes ;
7277 private readonly AccountsSettingsPaneConfig ? _accountsSettingsPaneConfig ;
7378 private readonly WebAccountProviderConfig _webAccountProviderConfig ;
74- private WebAccount _webAccount ;
79+ private WebAccount _webAccount = null ;
7580
7681 /// <summary>
7782 /// Initializes a new instance of the <see cref="WindowsProvider"/> class.
@@ -80,7 +85,8 @@ public class WindowsProvider : BaseProvider
8085 /// <param name="accountsSettingsPaneConfig">Configuration values for the AccountsSettingsPane.</param>
8186 /// <param name="webAccountProviderConfig">Configuration value for determining the available web account providers.</param>
8287 /// <param name="autoSignIn">Determines whether the provider attempts to silently log in upon construction.</param>
83- public WindowsProvider ( string [ ] scopes = null , WebAccountProviderConfig ? webAccountProviderConfig = null , AccountsSettingsPaneConfig ? accountsSettingsPaneConfig = null , bool autoSignIn = true )
88+ /// <param name="dispatcherQueue">The DispatcherQueue that should be used to dispatch UI updates, or null if this is being called from the UI thread.</param>
89+ public WindowsProvider ( string [ ] scopes = null , WebAccountProviderConfig ? webAccountProviderConfig = null , AccountsSettingsPaneConfig ? accountsSettingsPaneConfig = null , bool autoSignIn = true , DispatcherQueue dispatcherQueue = null )
8490 {
8591 _scopes = scopes ?? DefaultScopes ;
8692 _webAccountProviderConfig = webAccountProviderConfig ?? new WebAccountProviderConfig ( )
@@ -89,7 +95,7 @@ public WindowsProvider(string[] scopes = null, WebAccountProviderConfig? webAcco
8995 } ;
9096 _accountsSettingsPaneConfig = accountsSettingsPaneConfig ;
9197
92- _webAccount = null ;
98+ DispatcherQueue = dispatcherQueue ?? DispatcherQueue . GetForCurrentThread ( ) ;
9399
94100 State = ProviderState . SignedOut ;
95101
@@ -198,21 +204,7 @@ public override async Task<string> GetTokenAsync(bool silentOnly = false)
198204 }
199205
200206 // Attempt to authenticate interactively.
201- var tcs = new TaskCompletionSource < WebTokenRequestResult > ( ) ;
202- var taskQueued = DispatcherQueue . GetForCurrentThread ( ) . TryEnqueue ( async ( ) =>
203- {
204- var result = await AuthenticateInteractiveAsync ( _scopes ) ;
205- tcs . SetResult ( result ) ;
206- } ) ;
207-
208- if ( taskQueued )
209- {
210- authResult = await tcs . Task ;
211- }
212- else
213- {
214- tcs . SetCanceled ( ) ;
215- }
207+ authResult = await AuthenticateInteractiveAsync ( _scopes ) ;
216208 }
217209
218210 if ( authResult ? . ResponseStatus == WebTokenRequestStatus . Success )
@@ -249,15 +241,15 @@ public override async Task<string> GetTokenAsync(bool silentOnly = false)
249241 /// Display AccountSettingsPane for the management of logged-in users.
250242 /// </summary>
251243 /// <returns><see cref="Task"/>.</returns>
252- public async Task ShowAccountManagementPaneAsync ( )
244+ public Task ShowAccountManagementPaneAsync ( )
253245 {
254246 if ( _webAccount == null )
255247 {
256248 throw new InvalidOperationException ( "A logged in account is required to display the account management pane." ) ;
257249 }
258250
259251 var tcs = new TaskCompletionSource < bool > ( ) ;
260- _ = DispatcherQueue . GetForCurrentThread ( ) . TryEnqueue ( async ( ) =>
252+ var taskQueued = DispatcherQueue . TryEnqueue ( async ( ) =>
261253 {
262254 AccountsSettingsPane pane = null ;
263255 try
@@ -284,7 +276,12 @@ public async Task ShowAccountManagementPaneAsync()
284276 }
285277 } ) ;
286278
287- await tcs . Task ;
279+ if ( ! taskQueued )
280+ {
281+ tcs . SetException ( new InvalidOperationException ( "Failed to enqueue the operation." ) ) ;
282+ }
283+
284+ return tcs . Task ;
288285 }
289286
290287 /// <summary>
@@ -392,34 +389,45 @@ private async Task<WebTokenRequestResult> AuthenticateSilentAsync(string[] scope
392389 }
393390 }
394391
395- private async Task < WebTokenRequestResult > AuthenticateInteractiveAsync ( string [ ] scopes )
392+ private Task < WebTokenRequestResult > AuthenticateInteractiveAsync ( string [ ] scopes )
396393 {
397- try
394+ var tcs = new TaskCompletionSource < WebTokenRequestResult > ( ) ;
395+ var taskQueued = DispatcherQueue . TryEnqueue ( async ( ) =>
398396 {
399- WebTokenRequestResult authResult = null ;
400-
401- var account = _webAccount ;
402- if ( account != null )
397+ try
403398 {
404- // We already have the account.
405- var webAccountProvider = account . WebAccountProvider ;
406- var webTokenRequest = GetWebTokenRequest ( webAccountProvider , _webAccountProviderConfig . ClientId , scopes ) ;
407- authResult = await WebAuthenticationCoreManager . RequestTokenAsync ( webTokenRequest , account ) ;
399+ WebTokenRequestResult authResult = null ;
400+
401+ var account = _webAccount ;
402+ if ( account != null )
403+ {
404+ // We already have the account.
405+ var webAccountProvider = account . WebAccountProvider ;
406+ var webTokenRequest = GetWebTokenRequest ( webAccountProvider , _webAccountProviderConfig . ClientId , scopes ) ;
407+ authResult = await WebAuthenticationCoreManager . RequestTokenAsync ( webTokenRequest , account ) ;
408+ }
409+ else
410+ {
411+ // We don't have an account. Prompt the user to provide one.
412+ var webAccountProvider = await ShowAccountSettingsPaneAndGetProviderAsync ( ) ;
413+ var webTokenRequest = GetWebTokenRequest ( webAccountProvider , _webAccountProviderConfig . ClientId , scopes ) ;
414+ authResult = await WebAuthenticationCoreManager . RequestTokenAsync ( webTokenRequest ) ;
415+ }
416+
417+ tcs . SetResult ( authResult ) ;
408418 }
409- else
419+ catch ( Exception e )
410420 {
411- // We don't have an account. Prompt the user to provide one.
412- var webAccountProvider = await ShowAccountSettingsPaneAndGetProviderAsync ( ) ;
413- var webTokenRequest = GetWebTokenRequest ( webAccountProvider , _webAccountProviderConfig . ClientId , scopes ) ;
414- authResult = await WebAuthenticationCoreManager . RequestTokenAsync ( webTokenRequest ) ;
421+ tcs . SetException ( e ) ;
415422 }
423+ } ) ;
416424
417- return authResult ;
418- }
419- catch ( HttpRequestException )
425+ if ( ! taskQueued )
420426 {
421- throw ; /* probably offline, no point continuing to interactive auth */
427+ tcs . SetException ( new InvalidOperationException ( "Failed to enqueue the operation." ) ) ;
422428 }
429+
430+ return tcs . Task ;
423431 }
424432
425433 /// <summary>
0 commit comments