@prefix schema: <https://schema.org/> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix ks: <https://comcomponent.com/vocab/> .

<https://comcomponent.com/blog/2026/03/12/000-wpf-winforms-ui-thread-async-await-one-sheet/#article>
    schema:about <https://comcomponent.com/knowledge/ui-thread-context/>, <https://comcomponent.com/knowledge/wpf/>, <https://comcomponent.com/knowledge/windows-forms/> ;
    schema:mentions <https://comcomponent.com/knowledge/message-loop/>, <https://comcomponent.com/knowledge/synchronizationcontext/>, <https://comcomponent.com/knowledge/wpf-dispatcher/>, <https://comcomponent.com/knowledge/winforms-begininvoke/>, <https://comcomponent.com/knowledge/winforms-invokeasync/>, <https://comcomponent.com/knowledge/taskcompletionsource/>, <https://comcomponent.com/knowledge/cancellationtoken-dotnet/>, <https://comcomponent.com/knowledge/reentrancy-guard/>, <https://comcomponent.com/knowledge/cancel-execute-race/>, <https://comcomponent.com/knowledge/plain-await/>, <https://comcomponent.com/knowledge/configureawait-false/>, <https://comcomponent.com/knowledge/generic-library-code/>, <https://comcomponent.com/knowledge/taskrun-dotnet/>, <https://comcomponent.com/knowledge/io-bound-operation/>, <https://comcomponent.com/knowledge/ui-thread-blocking/>, <https://comcomponent.com/knowledge/sync-over-async/>, <https://comcomponent.com/knowledge/deadlock/>, <https://comcomponent.com/knowledge/task-result-wait/>, <https://comcomponent.com/knowledge/async-void/>, <https://comcomponent.com/knowledge/event-handler-method/>, <https://comcomponent.com/knowledge/ui-unhandled-exception-handler/> .

<https://comcomponent.com/knowledge/ui-thread-context/> a skos:Concept ;
    skos:prefLabel "UIスレッドのコンテキスト"@ja ;
    skos:definition "WinForms/WPFなどデスクトップアプリで、UIの応答性を保つために画面更新や重い処理の実行場所として意識されるコンテキスト。"@ja ;
    skos:altLabel "UIイベントハンドラ"@ja ;
    ks:requires <https://comcomponent.com/knowledge/message-loop/> .

<https://comcomponent.com/knowledge/wpf/> a skos:Concept ;
    skos:prefLabel "WPF"@ja ;
    skos:definition "XAMLでUIを宣言的に記述する、Windows専用のデスクトップUIフレームワーク。ベクターベースの描画とデータバインディングを特徴とする。"@ja ;
    skos:altLabel "Windows Presentation Foundation" ;
    ks:uses <https://comcomponent.com/knowledge/synchronizationcontext/> ;
    ks:uses <https://comcomponent.com/knowledge/wpf-dispatcher/> .

<https://comcomponent.com/knowledge/windows-forms/> a skos:Concept ;
    skos:prefLabel "Windows Forms"@ja ;
    skos:definition "デスクトップGUIアプリケーションを構築するための.NET/.NET FrameworkのUIフレームワーク。"@ja ;
    skos:altLabel "WinForms" ;
    ks:uses <https://comcomponent.com/knowledge/synchronizationcontext/> ;
    ks:uses <https://comcomponent.com/knowledge/winforms-begininvoke/> .

<https://comcomponent.com/knowledge/message-loop/> a skos:Concept ;
    skos:prefLabel "メッセージループ"@ja ;
    skos:definition "スレッドがGetMessage/DispatchMessageなどで自分のウィンドウ宛てのメッセージを順に取り出し処理し続ける仕組み。入力・描画・イベント処理を担うと同時に、STAが持つOleMainThreadWndClassという隠しウィンドウ宛てに届く、別アパートメントからの呼び出しメッセージもここでディスパッチされる。"@ja ;
    skos:altLabel "OleMainThreadWndClass" ;
    skos:broader <https://comcomponent.com/knowledge/com-apartment-model/> .

<https://comcomponent.com/knowledge/synchronizationcontext/> a skos:Concept ;
    skos:prefLabel "SynchronizationContext"@ja ;
    skos:definition "awaitした時点の実行コンテキストを表す.NETのクラス。捕捉されると、非同期処理完了後の継続がそのコンテキストへ投げ返される(例: WPF/WinFormsのUIスレッド)。"@ja .

<https://comcomponent.com/knowledge/wpf-dispatcher/> a skos:Concept ;
    skos:prefLabel "Dispatcher(WPF)"@ja ;
    skos:definition "WPFのUIスレッド上で処理を順番に実行するためのメッセージキューを管理するクラス。DispatcherTimerのTickもこのキューに積まれる。"@ja ;
    skos:altLabel "System.Windows.Threading.Dispatcher" ;
    skos:altLabel "UIスレッドのメッセージキュー"@ja ;
    ks:mayCause <https://comcomponent.com/knowledge/deadlock/> .

<https://comcomponent.com/knowledge/winforms-begininvoke/> a skos:Concept ;
    skos:prefLabel "Control.Invoke / Control.BeginInvoke"@ja ;
    skos:definition "WinFormsでUIスレッドへ処理を投げる旧来のAPI。Invokeは同期送信で呼び出し側を待たせ、BeginInvokeは投稿してすぐ返るが戻り値はIAsyncResultでそのままawaitできない。"@ja ;
    skos:altLabel "Control.BeginInvoke" ;
    skos:altLabel "Control.Invoke" ;
    skos:altLabel "同期送信/非同期投稿"@ja ;
    skos:broader <https://comcomponent.com/knowledge/windows-forms/> .

<https://comcomponent.com/knowledge/winforms-invokeasync/> a skos:Concept ;
    skos:prefLabel "Control.InvokeAsync"@ja ;
    skos:definition ".NET 9で追加された、WinFormsのControlがUIスレッドへ処理を投げるためのAPI。Taskを返しasyncフローと素直に噛み合う。"@ja ;
    skos:altLabel ".NET 9+ Control.InvokeAsync" ;
    skos:broader <https://comcomponent.com/knowledge/windows-forms/> ;
    ks:succeeds <https://comcomponent.com/knowledge/winforms-begininvoke/> .

<https://comcomponent.com/knowledge/taskcompletionsource/> a skos:Concept ;
    skos:prefLabel "TaskCompletionSource"@ja ;
    skos:definition "完了していないTaskを手動で作成し、後からTrySetResult/TrySetException/TrySetCanceledで結果・例外・キャンセルを確定させる.NETのクラス。イベントベースのAPIをTaskベースの非同期パターンへ橋渡しする際に使う。"@ja ;
    skos:altLabel "TaskCompletionSource<TResult>" .

<https://comcomponent.com/knowledge/cancellationtoken-dotnet/> a skos:Concept ;
    skos:prefLabel "CancellationToken(.NET)"@ja ;
    skos:definition ".NETの協調的キャンセルの仕組み。非同期モードのハンドルへのファイルI/Oでは、内部的にCancelIoExの呼び出しに行き着く。"@ja ;
    skos:altLabel "CancellationToken" .

<https://comcomponent.com/knowledge/reentrancy-guard/> a skos:Concept ;
    skos:prefLabel "再入防止ガード(Interlocked.Exchange等)"@ja ;
    skos:definition "Interlocked.Exchangeなどの原子的操作でフラグを立て、同じ処理が並行して重複実行されるのを防ぐ実装パターン。"@ja ;
    skos:altLabel "reentrancy guard" ;
    skos:altLabel "多重実行防止"@ja ;
    ks:prevents <https://comcomponent.com/knowledge/cancel-execute-race/> .

<https://comcomponent.com/knowledge/cancel-execute-race/> a skos:Concept ;
    skos:prefLabel "キャンセルと実行が競合するレース"@ja ;
    skos:definition "対象のCancellationTokenがキャンセルされる経路と、投稿済みデリゲートが実行される経路が、どちらも「1回ぶんの完了」を確定させようとして競合する状態。キャンセル済みかを確認してから動く実装では、確認した直後にもう一方が割り込む隙間が残る。"@ja ;
    skos:altLabel "キャンセル後の古いデリゲート実行"@ja ;
    skos:altLabel "check-then-actの隙間"@ja .

<https://comcomponent.com/knowledge/plain-await/> a skos:Concept ;
    skos:prefLabel "plain await"@ja ;
    skos:definition "ConfigureAwait(false)を付けない既定のawait。その時点のSynchronizationContext.Current(無ければTaskScheduler.Current)を捕まえ、完了後の継続をそこへ戻そうとする。"@ja ;
    skos:altLabel "素のawait"@ja ;
    skos:altLabel "ConfigureAwaitなしのawait"@ja ;
    ks:uses <https://comcomponent.com/knowledge/synchronizationcontext/> ;
    ks:recommendedFor <https://comcomponent.com/knowledge/ui-thread-context/> .

<https://comcomponent.com/knowledge/configureawait-false/> a skos:Concept ;
    skos:prefLabel "ConfigureAwait(false)"@ja ;
    skos:definition "awaitの継続を、捕捉したSynchronizationContextやTaskSchedulerへ投げ返さないことを指示する.NETの記法。「必ずスレッドプールへ移る」保証ではない。"@ja ;
    ks:notRecommendedFor <https://comcomponent.com/knowledge/ui-thread-context/> ;
    ks:recommendedFor <https://comcomponent.com/knowledge/generic-library-code/> .

<https://comcomponent.com/knowledge/generic-library-code/> a skos:Concept ;
    skos:prefLabel "汎用ライブラリコード"@ja ;
    skos:definition "UIやASP.NET Coreなど特定のアプリモデルに依存せず、どちらから呼ばれるか分からない前提で書く再利用可能なコード。"@ja ;
    skos:altLabel "ライブラリコード"@ja .

<https://comcomponent.com/knowledge/taskrun-dotnet/> a skos:Concept ;
    skos:prefLabel "Task.Run"@ja ;
    skos:definition "CPUを使う処理を.NETスレッドプールのワーカースレッドへ明示的にオフロードするためのAPI。I/OバウンドのTaskに使う必要はない。"@ja ;
    ks:recommendedFor <https://comcomponent.com/knowledge/ui-thread-context/> ;
    ks:notRecommendedFor <https://comcomponent.com/knowledge/io-bound-operation/> ;
    ks:prevents <https://comcomponent.com/knowledge/ui-thread-blocking/> .

<https://comcomponent.com/knowledge/io-bound-operation/> a skos:Concept ;
    skos:prefLabel "I/O-bound処理"@ja ;
    skos:definition "HTTP、DB、ファイル、ソケットなど、外部の完了待ちが中心の処理。待っている間にスレッドを他の仕事へ返せる。"@ja ;
    skos:altLabel "I/O待ち"@ja .

<https://comcomponent.com/knowledge/ui-thread-blocking/> a skos:Concept ;
    skos:prefLabel "UIスレッドの詰まり"@ja ;
    skos:definition "UIスレッド上で重い処理やブロッキングI/Oが実行され、入力処理や画面描画が遅延・停止する状態。"@ja ;
    skos:altLabel "UI応答性の低下"@ja ;
    skos:altLabel "UIブロッキング"@ja .

<https://comcomponent.com/knowledge/sync-over-async/> a skos:Concept ;
    skos:prefLabel "同期待ちの混入(sync-over-async)"@ja ;
    skos:definition "非同期処理の継続やワーカーの中で、同期I/OやTask.Result/Wait()のような同期的な待ちを行ってしまうアンチパターン。スレッドプール飢餓の主因になる。"@ja ;
    skos:altLabel "sync-over-async" ;
    ks:mayCause <https://comcomponent.com/knowledge/deadlock/> .

<https://comcomponent.com/knowledge/deadlock/> a skos:Concept ;
    skos:prefLabel "デッドロック(deadlock)"@ja ;
    skos:definition "複数のタスクが互いの完了やリソース解放を待ち続け、永遠に進行しなくなる状態である。"@ja ;
    skos:altLabel "Deadlock" .

<https://comcomponent.com/knowledge/task-result-wait/> a skos:Concept ;
    skos:prefLabel ".Result / .Wait() / .GetAwaiter().GetResult()"@ja ;
    skos:definition "Taskの完了を同期的に待つ3つの手段の総称。呼び出し元のスレッドをブロックする点は共通で、違うのは主に例外の包まれ方だけである。"@ja ;
    skos:altLabel "同期的なTask待機"@ja ;
    skos:altLabel "GetAwaiter().GetResult()" ;
    ks:notRecommendedFor <https://comcomponent.com/knowledge/ui-thread-context/> .

<https://comcomponent.com/knowledge/async-void/> a skos:Concept ;
    skos:prefLabel "async void"@ja ;
    skos:definition "戻り値を持たないasyncメソッド。呼び出し元がawaitできず、完了を待てず、例外処理が難しくテストもしづらい。"@ja ;
    ks:recommendedFor <https://comcomponent.com/knowledge/event-handler-method/> ;
    ks:mayCause <https://comcomponent.com/knowledge/ui-unhandled-exception-handler/> .

<https://comcomponent.com/knowledge/event-handler-method/> a skos:Concept ;
    skos:prefLabel "イベントハンドラメソッド"@ja ;
    skos:definition "UIフレームワークがシグネチャ上voidを要求する、ボタンクリックなどのイベントに応答するメソッド。"@ja ;
    skos:altLabel "イベントハンドラ"@ja .

<https://comcomponent.com/knowledge/ui-unhandled-exception-handler/> a skos:Concept ;
    skos:prefLabel "UIの全体受け皿(DispatcherUnhandledException / ThreadException)"@ja ;
    skos:definition "UIスレッドの未処理例外を最後に受け取る、WPFのApplication.DispatcherUnhandledExceptionとWinFormsのApplication.ThreadExceptionの総称。async voidから投げ直された例外もここに届く。"@ja ;
    skos:altLabel "Application.DispatcherUnhandledException" ;
    skos:altLabel "Application.ThreadException" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/ui-thread-context/> ;
    rdf:predicate ks:requires ;
    rdf:object <https://comcomponent.com/knowledge/message-loop/> ;
    schema:description "WPF/WinFormsのUIスレッドは、入力・描画・イベント処理を順に取り出して処理するメッセージループを回し続けることで応答性を保つ。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/threading-model> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/wpf/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/synchronizationcontext/> ;
    schema:description "WPFのUIスレッドにはDispatcherSynchronizationContextが設定されており、SynchronizationContext.Currentとして取得できる。"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.threading.dispatchersynchronizationcontext?view=windowsdesktop-10.0> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/windows-forms/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/synchronizationcontext/> ;
    schema:description "WinFormsのUIスレッドにはWindowsFormsSynchronizationContextが設定されている。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.windowsformssynchronizationcontext?view=windowsdesktop-10.0> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/wpf/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/wpf-dispatcher/> ;
    schema:description "WPFはUIスレッド用のメッセージキューであるDispatcherを持ち、明示的にUIへ戻す代表APIはDispatcher.InvokeAsyncである。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/threading-model> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/windows-forms/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/winforms-begininvoke/> ;
    schema:description "WinFormsの旧来パターンでは、UIスレッドへ処理を投げるのにControl.Invoke(同期送信)またはControl.BeginInvoke(非同期投稿、戻り値はIAsyncResult)を使う。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.begininvoke> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/windows-forms/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/winforms-invokeasync/> ;
    schema:description ".NET 9以降のWinFormsでは、Taskを返しasyncフローと素直に噛み合うControl.InvokeAsyncが使える。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.invokeasync> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "context-dependent" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/winforms-invokeasync/> ;
    rdf:predicate ks:succeeds ;
    rdf:object <https://comcomponent.com/knowledge/winforms-begininvoke/> ;
    schema:description "Control.InvokeAsyncは.NET 9で追加され、Control.BeginInvoke/Invokeに代わってasyncフローと噛み合う戻し先として使える。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.invokeasync> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/winforms-begininvoke/> ;
    rdf:predicate ks:requires ;
    rdf:object <https://comcomponent.com/knowledge/taskcompletionsource/> ;
    schema:description "Control.BeginInvokeが返すIAsyncResultはそのままawaitできないため、Control.InvokeAsyncが無い環境(.NET Framework 4.8、.NET 6/8など)でasyncフローに乗せるにはTaskCompletionSourceで包む必要がある。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.begininvoke> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "context-dependent" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/taskcompletionsource/> ;
    rdf:predicate ks:requires ;
    rdf:object <https://comcomponent.com/knowledge/cancellationtoken-dotnet/> ;
    schema:description "本記事のInvokeOnUiAsyncのように、コントロールが破棄されてBeginInvoke経由のデリゲートが実行されずに捨てられる事態に備えてキャンセルで畳みたい設計に限る。記事のInvokeOnUiAsync拡張メソッドはCancellationTokenを必須引数にしているが、TaskCompletionSource自体はCancellationTokenなしでも動作する汎用の型である。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcompletionsource-1> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "context-dependent" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/taskcompletionsource/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/reentrancy-guard/> ;
    schema:description "本記事のInvokeOnUiAsyncのように、キャンセル側とBeginInvokeで実行されるデリゲート側のどちらか一方だけが結果を確定できるようにしたい場合、TaskCompletionSourceはInterlocked.Exchangeで用意した「1回ぶんの権利」と組み合わせて使われる。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/api/system.threading.interlocked.exchange> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "context-dependent" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/reentrancy-guard/> ;
    rdf:predicate ks:prevents ;
    rdf:object <https://comcomponent.com/knowledge/cancel-execute-race/> ;
    schema:description "「キャンセル済みか確認してからaction()を呼ぶ」という判定と実行を分けた実装だと、確認直後にキャンセルが割り込む一瞬が残り、キューに残っていた古いデリゲートが後から実行されて新しい表示を上書きしてしまう。Interlocked.Exchangeで権利そのものを奪い合わせ、取れなかった側は必ず何もせずに帰るようにすることでこの競合を防ぐ。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/api/system.threading.interlocked.exchange> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/plain-await/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/synchronizationcontext/> ;
    schema:description "既定のawait(ConfigureAwaitなし)は、その時点のSynchronizationContext.Currentをまず捕まえ継続をそこへ戻そうとする。それがnullのときだけTaskScheduler.Currentを見て、TaskScheduler.Defaultでなければそのスケジューラへ、どちらでもなければ継続はThreadPool上で走る。"@ja ;
    ks:evidence <https://devblogs.microsoft.com/dotnet/how-async-await-really-works/> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/plain-await/> ;
    rdf:predicate ks:recommendedFor ;
    rdf:object <https://comcomponent.com/knowledge/ui-thread-context/> ;
    schema:description "UIイベントハンドラで待つ処理は、余計なDispatcher/Invokeを使わず素のawaitのままにするのが本記事の方針で、待ち中はメッセージループへ戻り完了後の続きはUIスレッドへ戻るためそのままUIを更新できる。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/threading-model> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/configureawait-false/> ;
    rdf:predicate ks:requires ;
    rdf:object <https://comcomponent.com/knowledge/synchronizationcontext/> ;
    schema:description "そのawaitがSynchronizationContext(またはデフォルト以外のTaskScheduler)を捕捉していた場合に限り、ConfigureAwait(false)はそこへ継続を戻すことを強制しないという意味を持つ。コンソールアプリやThreadPool上で動くライブラリコードのようにそもそもコンテキストが無い状況でも問題なく使え、その場合はplain awaitとの差がほとんど無い。"@ja ;
    ks:evidence <https://devblogs.microsoft.com/dotnet/configureawait-faq/> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "context-dependent" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/configureawait-false/> ;
    rdf:predicate ks:notRecommendedFor ;
    rdf:object <https://comcomponent.com/knowledge/ui-thread-context/> ;
    schema:description "UIハンドラ自身でConfigureAwait(false)を付けると、その続きがUIに戻ることを強制しなくなり、直後のUI更新がクロススレッドアクセスになりかねないため、本記事はUIコードでの使用を避ける方針を取る。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-make-thread-safe-calls> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/configureawait-false/> ;
    rdf:predicate ks:recommendedFor ;
    rdf:object <https://comcomponent.com/knowledge/generic-library-code/> ;
    schema:description "UIや特定アプリモデルに依存しない汎用ライブラリコード(記事中のDocumentRepositoryのような形)にはConfigureAwait(false)を付けるのが自然で、呼び出し元のUIハンドラは素のawaitのままでよい分離ができる。"@ja ;
    ks:evidence <https://devblogs.microsoft.com/dotnet/configureawait-faq/> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/taskrun-dotnet/> ;
    rdf:predicate ks:recommendedFor ;
    rdf:object <https://comcomponent.com/knowledge/ui-thread-context/> ;
    schema:description "Task.RunはCPU計算をUIスレッドから外すためのものであり、UIイベントハンドラで重いハッシュ計算などを行うときに使うのが本記事の推奨である。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/threading-model> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/taskrun-dotnet/> ;
    rdf:predicate ks:notRecommendedFor ;
    rdf:object <https://comcomponent.com/knowledge/io-bound-operation/> ;
    schema:description "Task.Run(async () => await File.ReadAllTextAsync(...))のようにI/O待ちをTask.Runで包む書き方は、待ちを無駄にThreadPoolへ投げ直しているだけで得がないと本記事は述べる。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/async-scenarios> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/taskrun-dotnet/> ;
    rdf:predicate ks:prevents ;
    rdf:object <https://comcomponent.com/knowledge/ui-thread-blocking/> ;
    schema:description "重いCPU計算をTask.RunでThreadPoolへ逃がすことで、UIスレッドのメッセージループが塞がれて画面が固まって見える状態を避けられる。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/threading-model> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/sync-over-async/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/deadlock/> ;
    schema:description "UIスレッドが.Resultや.Wait()で同期的に待つ間、非同期処理の継続はキャプチャしたUIコンテキストへ戻ろうとするが、UIスレッドは待ちで塞がっているため継続が実行できず、互いに待ち合うデッドロックになりうる。"@ja ;
    ks:evidence <https://devblogs.microsoft.com/dotnet/await-and-ui-and-deadlocks-oh-my/> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/task-result-wait/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/deadlock/> ;
    schema:description "UIスレッドで.Result/.Wait()/.GetAwaiter().GetResult()を呼ぶと、呼び出した先のawaitが捕まえたUIコンテキストへ継続が戻れなくなる。必ずデッドロックするとは限らず、たまたま継続がUIに戻らないコードなら単にUIをフリーズさせるだけのこともある。"@ja ;
    ks:evidence <https://devblogs.microsoft.com/dotnet/await-and-ui-and-deadlocks-oh-my/> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "context-dependent" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/task-result-wait/> ;
    rdf:predicate ks:notRecommendedFor ;
    rdf:object <https://comcomponent.com/knowledge/ui-thread-context/> ;
    schema:description "本記事は.Result・.Wait()・.GetAwaiter().GetResult()の3つを同じ匂いとして扱い、UIでは使わない方針を取る。GetAwaiter().GetResult()も例外の包まれ方が違うだけでUIスレッドを塞ぐ本質は同じとしている。"@ja ;
    ks:evidence <https://devblogs.microsoft.com/dotnet/await-and-ui-and-deadlocks-oh-my/> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/wpf-dispatcher/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/deadlock/> ;
    schema:description "Dispatcher.InvokeAsyncが返すDispatcherOperationのTaskをUIスレッドからTask.Wait()すると、Dispatcherのキューを回すのは同じUIスレッドなので待ちで止まったままキューが進まず完了しない。DispatcherOperation.Wait()自身も、同じスレッドで実行中の操作を待つとInvalidOperationExceptionになると明記されている。"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.threading.dispatcher.invokeasync?view=windowsdesktop-10.0>, <https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.threading.dispatcheroperation.wait?view=windowsdesktop-10.0> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/async-void/> ;
    rdf:predicate ks:recommendedFor ;
    rdf:object <https://comcomponent.com/knowledge/event-handler-method/> ;
    schema:description "UIイベントハンドラのシグネチャがvoidを要求するため、そこだけ例外的にasync voidが許され、本記事はハンドラの中でtry/catchして失敗を画面表示に変える形を基本とする。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/desktop/winforms/forms/events> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/async-void/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/ui-unhandled-exception-handler/> ;
    schema:description "async voidのハンドラでtry/catchせずに例外が外へ抜けると、そのハンドラが開始したときのSynchronizationContext、つまりUIスレッドへ投げ直され、WPFならApplication.DispatcherUnhandledException、WinFormsならApplication.ThreadExceptionに届く。そこで処理しなければアプリが落ちる。"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/api/system.windows.application.dispatcherunhandledexception>, <https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.application.threadexception> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/event-handler-method/> ;
    rdf:predicate ks:requires ;
    rdf:object <https://comcomponent.com/knowledge/ui-thread-context/> ;
    schema:description "UIイベントハンドラ(Click等)はUIスレッドのコンテキスト上で開始することが前提になっており、これがawait後の継続の戻り先を決める起点になる。UIフレームワークがUIスレッド上でハンドラーを起動する構成での話である"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/desktop/winforms/forms/events> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "context-dependent" .
