Dialogs await their Task through a generic #:async import
Bjolang now resolves a generic method imported #:async, so Dispatcher.InvokeAsync(Func<Task<T>>) is imported as it is: it runs the dialog on the UI thread and is awaited for what the dialog answers. The detour through the non-generic Task.WhenAll and the Result read by reflection are gone. 🤖 Generated with [ECA](https://eca.dev) (anthropic/claude-opus-4-8) Co-Authored-By: eca-agent <git@eca.dev>
This commit is contained in:
parent
8941425f05
commit
f53877e7a1
1 changed files with 9 additions and 26 deletions
|
|
@ -29,9 +29,6 @@
|
||||||
|
|
||||||
(import/class
|
(import/class
|
||||||
(Object (: System.Object))
|
(Object (: System.Object))
|
||||||
(DispatcherOpBase (: Avalonia.Threading.DispatcherOperation))
|
|
||||||
(ClrType (: System.Type))
|
|
||||||
(PropertyInfo (: System.Reflection.PropertyInfo))
|
|
||||||
(ClrString (: System.String))
|
(ClrString (: System.String))
|
||||||
((ReadOnlyList %a) (: System.Collections.Generic.IReadOnlyList))
|
((ReadOnlyList %a) (: System.Collections.Generic.IReadOnlyList))
|
||||||
((EventHandler %a) (: System.EventHandler))
|
((EventHandler %a) (: System.EventHandler))
|
||||||
|
|
@ -77,20 +74,12 @@
|
||||||
;; The UI thread, and the window a dialog belongs to.
|
;; The UI thread, and the window a dialog belongs to.
|
||||||
(ui-dispatcher (: Avalonia.Threading.Dispatcher.UIThread #:get))
|
(ui-dispatcher (: Avalonia.Threading.Dispatcher.UIThread #:get))
|
||||||
(ui-post (: Avalonia.Threading.Dispatcher.InvokeAsync (-> Dispatcher (-> Unit) (DispatcherOp Unit))))
|
(ui-post (: Avalonia.Threading.Dispatcher.InvokeAsync (-> Dispatcher (-> Unit) (DispatcherOp Unit))))
|
||||||
;; Runs a function on the UI thread.
|
;; Runs a function that starts a Task on the UI thread, and waits for the
|
||||||
|
;; Task. Avalonia's dialogs take no CancellationToken, so this cannot be
|
||||||
|
;; cancelled: a cancelled command stops waiting, and the dialog stays until
|
||||||
|
;; it is answered.
|
||||||
(on-ui (: Avalonia.Threading.Dispatcher.InvokeAsync
|
(on-ui (: Avalonia.Threading.Dispatcher.InvokeAsync
|
||||||
(-> Dispatcher (-> Unit) (DispatcherOp Unit))))
|
(-> Dispatcher (-> (Task %a)) %a) #:async #:uncancellable))
|
||||||
(op-task (: Avalonia.Threading.DispatcherOperation.GetTask (-> DispatcherOpBase Task)))
|
|
||||||
;; Waits for Tasks. Avalonia's dialogs take no CancellationToken, so this
|
|
||||||
;; cannot be cancelled: a cancelled command stops at its next sync, and the
|
|
||||||
;; dialog stays until it is answered.
|
|
||||||
(await-tasks (: System.Threading.Tasks.Task.WhenAll (-> (Array Task) void)
|
|
||||||
#:async #:uncancellable))
|
|
||||||
;; What a finished Task answers. By reflection, because Bjolang reads no
|
|
||||||
;; Task's Result: on a Task that is not finished, that would block.
|
|
||||||
(type-of (: System.Object.GetType (-> Object ClrType)))
|
|
||||||
(property-of (: System.Type.GetProperty (-> ClrType string PropertyInfo)))
|
|
||||||
(value-of (: System.Reflection.PropertyInfo.GetValue (-> PropertyInfo Object Object)))
|
|
||||||
(answered (: System.Threading.Tasks.Task.FromResult (-> %a (Task %a))))
|
(answered (: System.Threading.Tasks.Task.FromResult (-> %a (Task %a))))
|
||||||
(current-app (: Avalonia.Application.Current #:get))
|
(current-app (: Avalonia.Application.Current #:get))
|
||||||
(app-lifetime (: Avalonia.Application.ApplicationLifetime (-> Application ILifetime) #:get))
|
(app-lifetime (: Avalonia.Application.ApplicationLifetime (-> Application ILifetime) #:get))
|
||||||
|
|
@ -171,16 +160,10 @@
|
||||||
;; Task it makes. `none` is the answer when there is no window.
|
;; Task it makes. `none` is the answer when there is no window.
|
||||||
(: (-bjo-> (-> Window (Task %a)) %a %a))
|
(: (-bjo-> (-> Window (Task %a)) %a %a))
|
||||||
(defbjo (run-on-ui start none)
|
(defbjo (run-on-ui start none)
|
||||||
(def/mutable task (: (clr-default) Task))
|
(on-ui ui-dispatcher
|
||||||
(def op (on-ui ui-dispatcher
|
(fun () (match (owner)
|
||||||
(fun ()
|
((Some w) (start w))
|
||||||
(set! task (cast Task (cast Object (match (owner)
|
(None (answered none))))))
|
||||||
((Some w) (start w))
|
|
||||||
(None (answered none))))))
|
|
||||||
unit)))
|
|
||||||
(await-tasks #[(op-task (cast DispatcherOpBase (cast Object op)))])
|
|
||||||
(await-tasks #[task])
|
|
||||||
(cast %a (value-of (property-of (type-of (cast Object task)) "Result") (cast Object task))))
|
|
||||||
|
|
||||||
;; The event of what the Task that `start` makes answers, at each sync.
|
;; The event of what the Task that `start` makes answers, at each sync.
|
||||||
;; `none` is the answer when there is no window, or the Task fails.
|
;; `none` is the answer when there is no window, or the Task fails.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue