.NET MAUI

Concurrency & Threading

5 question(s)

What is the UI thread and why must UI updates happen on it?

Beginner
Each platform has a single main/UI thread that owns the visual tree; touching UI from another thread causes exceptions or corruption. Async I/O runs off the UI thread, but results that mutate UI must be marshaled back with MainThread.BeginInvokeOnMainThread (or InvokeOnMainThreadAsync).
MainThread.BeginInvokeOnMainThread(() => statusLabel.Text = "Done");
Real-world example A background download updates a progress label only after marshaling back to the UI thread, avoiding a cross-thread crash.

Common follow-ups: How do you check if you're on the UI thread? | What runs off the UI thread?

Threading Performance & Optimization Concurrency & Threading

How do you run CPU-bound work without blocking the UI?

Intermediate
Offload CPU-bound work with Task.Run so it executes on a thread-pool thread, await the result, then update UI on the main thread. Don't use Task.Run for I/O (await the async API directly). Keep the UI responsive by never blocking it with .Result or .Wait().
var result = await Task.Run(() => ExpensiveCompute(data));
resultLabel.Text = result.ToString();   // back on UI thread after await
Real-world example Image processing runs on a background thread via Task.Run so the UI stays responsive, then shows the result.

Common follow-ups: Why not Task.Run for I/O? | Why avoid .Result?

Threading Async Concurrency & Threading

What are common async/await pitfalls in MAUI?

Intermediate
Avoid async void except for event handlers (it swallows exceptions); don't block with .Result/.Wait() (deadlocks/UI freeze); use ConfigureAwait appropriately in library code; and handle exceptions in fire-and-forget tasks. Prefer async Task and propagate cancellation with CancellationToken.
// Bad: async void hides exceptions
async void Load() { await FetchAsync(); }
// Better: async Task, awaited or safely handled
async Task LoadAsync() { await FetchAsync(); }
Real-world example A silent failure disappears once a fire-and-forget async void is converted to an awaited async Task with try/catch.

Common follow-ups: When is async void acceptable? | How do you cancel async work?

Async Testing & Debugging Concurrency & Threading

How do you cancel long-running operations in MAUI?

Advanced
Pass a CancellationToken through async calls and trigger it with a CancellationTokenSource when the user navigates away or cancels. Check the token in loops and pass it to cancellation-aware APIs (HttpClient, delays). Dispose the source and handle OperationCanceledException.
_cts = new CancellationTokenSource();
try { await _api.SearchAsync(query, _cts.Token); }
catch (OperationCanceledException) { /* ignore */ }
// On new keystroke: _cts.Cancel();
Real-world example A type-ahead search cancels the in-flight request on each new keystroke so only the latest query completes.

Common follow-ups: Where do you check the token? | What exception signals cancellation?

Async Networking & APIs Concurrency & Threading

How do you safely update collections bound to the UI from background threads?

Advanced
Marshal collection mutations to the UI thread, since CollectionView observes changes on the UI thread. Compute/fetch data in the background, then add items via MainThread.BeginInvokeOnMainThread, or gather results and assign once. Some toolkit collections offer thread-safe patterns, but explicit marshaling is safest.
var page = await _api.GetPageAsync();
MainThread.BeginInvokeOnMainThread(() =>
{
    foreach (var item in page) Items.Add(item);
});
Real-world example Paged results fetched off-thread are appended to the bound ObservableCollection on the UI thread to avoid exceptions.

Common follow-ups: Why marshal collection changes? | Can you assign the whole collection at once?

Threading Collections Concurrency & Threading