postit: drop ConfigureAwait(false) after interactive login
LoginAsync uses ConfigureAwait(false) on the await of LoginInteractiveCoreAsync. Since the surrounding code is already executing on the UI thread (it was reached via a RelayCommand that the UI dispatcher dispatched), the ConfigureAwait drops the SynchronizationContext, and the subsequent setters — IsBusy, AccessToken, StatusMessage, LoginSuccess, and the LoginSucceeded?.Invoke() — run on a thread-pool worker. The downstream effects are all UI-bound: PropertyChanged events fire, the BindingEngine republishes them as AvaloniaObject.SetValue calls, and SetValue calls Dispatcher.VerifyAccess. VerifyAccess throws because the AvaloniaObject was created on the UI thread (owned by it) and the SetValue is being attempted from a thread-pool worker. Avalonia 11.12 throws SynchronousException through DispatcherOperation.InvokeCore instead of dispatching back, so the X11 message loop crashes the process with System.InvalidOperationException: 'The calling thread cannot access this object because a different thread owns it.' Reproduced with the freshly installed postit_1.0.0-1_amd64.deb package on a Debian 13 host — the .NET runtime loaded the app, Avalonia started the X11 message loop, the operator clicked 'Se connecter', the OIDC flow reached the post-login phase, and the post-await setter chain crashed the process. Drop ConfigureAwait(false) so the await captures the UI thread SynchronizationContext and the setters resume on the UI thread. The inner LoginInteractiveCoreAsync still uses ConfigureAwait(false) for its own await, which is fine — the inner method does not touch observables, only mutates Platform.CreateBrowser and awaits the OIDC roundtrip, so it can run anywhere.
This commit is contained in:
parent
4566223a2c
commit
4e8402e766
1 changed files with 1 additions and 1 deletions
|
|
@ -262,7 +262,7 @@ public partial class LoginPageViewModel : ViewModelBase
|
|||
// keeps the text detail (URLs, error messages). Same
|
||||
// underlying flow, two views.
|
||||
var progress = new Progress<OidcLoginPhase>(p => Phase = p);
|
||||
await LoginInteractiveCoreAsync(_api, progress).ConfigureAwait(false);
|
||||
await LoginInteractiveCoreAsync(_api, progress);
|
||||
|
||||
IsBusy = false;
|
||||
AccessToken = _api.CurrentAccessToken;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue