create_async在UI线程的行为及内部异步任务执行时机问询
Great question! Let's break down exactly how create_async behaves on the UI thread and walk through the execution timing of your code step by step.
create_async Behaves on the UI Thread When you call create_async from the UI thread (a single-threaded apartment/STA thread), the asynchronous operation it creates is bound to the current UI thread's context by default. This means any task continuations (like your .then callback) will automatically schedule back to the UI thread unless you explicitly specify otherwise—this matches what you've read about context-aware tasks sticking to their originating apartment thread.
Let's walk through what happens when you call GetImage() from the UI thread:
Immediate return of
IAsyncOperation
As soon as you callGetImage(),create_asyncwill instantly hand you back anIAsyncOperation<BitmapImage^>object. The lambda you passed tocreate_asyncdoesn't run right away—it gets queued to the UI thread's message loop, waiting for the current batch of synchronous UI work (like the event handler that calledGetImage(), ongoing rendering, or other pending UI tasks) to finish.Execution of the outer lambda &
GetStreamAsync()
Once the UI thread is free (its message loop picks up the queued task), the outer lambda runs. Inside it,create_task(GetStreamAsync())kicks off theGetStreamAsync()operation.- If
GetStreamAsync()is an I/O-bound operation (like fetching a file or network stream), its core work will likely run on a background thread (this depends on howGetStreamAsyncis implemented). But regardless of where it runs, the continuation (your.thencallback) will default back to the UI thread context.
- If
The
.thencallback runs on the UI thread
WhenGetStreamAsync()completes, the.thencallback is queued to the UI thread's message loop again. It won't interrupt any ongoing UI work—only when the thread is free will it execute.
Inside this callback, you create theBitmapImageand callSetSourceAsync(stream). A quick note here: your current code doesn't wait forSetSourceAsyncto finish before returning theBitmapImage. That's okay for most UI binding scenarios (theBitmapImagewill update automatically once loaded), but if you need to guarantee the image is fully loaded before returning, you should wrapSetSourceAsyncin a task and await it:return create_task(image->SetSourceAsync(stream)).then([image] { return image; });Returning the
BitmapImage
Once the.thencallback finishes, the result is propagated back through theIAsyncOperationto whatever is awaitingGetImage().
- All UI-thread-bound tasks (the
create_asynclambda, the.thencallback) are queued and executed in order—they never preempt currently running UI code. - If you wanted part of the workflow to run on a background thread (e.g., processing the stream before creating the
BitmapImage), you could override the continuation context withtask_continuation_context::use_arbitrary()in your.thencall. But since you're working withBitmapImage(a UI element), you must create it and callSetSourceAsyncon the UI thread.
内容的提问来源于stack exchange,提问作者Craig

