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
|
||||
(Object (: System.Object))
|
||||
(DispatcherOpBase (: Avalonia.Threading.DispatcherOperation))
|
||||
(ClrType (: System.Type))
|
||||
(PropertyInfo (: System.Reflection.PropertyInfo))
|
||||
(ClrString (: System.String))
|
||||
((ReadOnlyList %a) (: System.Collections.Generic.IReadOnlyList))
|
||||
((EventHandler %a) (: System.EventHandler))
|
||||
|
|
@ -77,20 +74,12 @@
|
|||
;; The UI thread, and the window a dialog belongs to.
|
||||
(ui-dispatcher (: Avalonia.Threading.Dispatcher.UIThread #:get))
|
||||
(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
|
||||
(-> Dispatcher (-> Unit) (DispatcherOp Unit))))
|
||||
(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)))
|
||||
(-> Dispatcher (-> (Task %a)) %a) #:async #:uncancellable))
|
||||
(answered (: System.Threading.Tasks.Task.FromResult (-> %a (Task %a))))
|
||||
(current-app (: Avalonia.Application.Current #: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.
|
||||
(: (-bjo-> (-> Window (Task %a)) %a %a))
|
||||
(defbjo (run-on-ui start none)
|
||||
(def/mutable task (: (clr-default) Task))
|
||||
(def op (on-ui ui-dispatcher
|
||||
(fun ()
|
||||
(set! task (cast Task (cast Object (match (owner)
|
||||
(on-ui ui-dispatcher
|
||||
(fun () (match (owner)
|
||||
((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.
|
||||
;; `none` is the answer when there is no window, or the Task fails.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue