Skip to main content

Invoke Feature

The Invoke feature dispatches work to the window's native thread. All UI operations in InfiniFrame must run on the thread that called Build(). This feature provides synchronous and asynchronous mechanisms to marshal work from background threads.

Contents

Why Cross-Thread Dispatch Is Needed

InfiniFrame windows are single-threaded. The native window (WebView2 on Windows, WebKitGTK on Linux, WKWebView on macOS) runs on a specific thread. Any call that modifies the window changing the title, resizing, navigating, closing must happen on that thread.

If you're on a background thread (e.g., from Task.Run or an async continuation), use Invoke or DispatchAsync to marshal the work:

Task.Run(() => {
// Background thread cannot call window methods directly
window.Invoke(() => {
// Now on the window thread safe to call window methods
window.SetTitle("Updated from background");
window.Close();
});
});

Synchronous Invoke

Invoke blocks the calling thread until the callback completes on the window thread:

window.Invoke(() => {
window.SetTitle("New Title");
window.Close();
});

The extension method form returns the window for chaining:

window.Invoke(() => window.SetTitle("New Title"));
warning

Invoke is synchronous and blocks the calling thread. If the window thread is busy (e.g., handling a dialog), this will deadlock. Prefer DispatchAsync for background work.

Asynchronous Dispatch

DispatchAsync queues the callback on the window thread without blocking the caller. It supports timeout and cancellation:

InfiniFrameDispatchResult result = await window.DispatchAsync(() => {
window.SetTitle("Updated from background");
}, timeout: TimeSpan.FromSeconds(5), cancellationToken: ct);

DispatchAsync is non-blocking and returns immediately. The callback is executed on the window thread when it becomes available.

Dispatch Result

InfiniFrameDispatchResult indicates the outcome of the dispatch:

ValueDescription
CompletedThe callback executed successfully
TimedOutThe timeout elapsed before the callback could execute
CancelledThe cancellation token was triggered
WindowClosedThe window was closed before the callback could execute
FailedThe callback threw an exception
InfiniFrameDispatchResult result = await window.DispatchAsync(() => {
// Work that may fail
}, timeout: TimeSpan.FromSeconds(10));

switch (result) {
case InfiniFrameDispatchResult.Completed:
Console.WriteLine("Done");
break;
case InfiniFrameDispatchResult.TimedOut:
Console.WriteLine("Window thread busy, try again later");
break;
case InfiniFrameDispatchResult.WindowClosed:
Console.WriteLine("Window already closed");
break;
}

See Also