次のコードは、実際のアプリケーションのコードを単純化したものです。以下の問題は、長いスレッドがバックグラウンドスレッドではなくUIスレッドで実行されることです。UIスレッドでタスクを実行しないようにする方法
void Do()
{
Debug.Assert(this.Dispatcher.CheckAccess() == true);
Task.Factory.StartNew(ShortUIWork, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}
void ShortUIWork()
{
Debug.Assert(this.Dispatcher.CheckAccess() == true);
Task.Factory.StartNew(LongWork, TaskCreationOptions.LongRunning);
}
void LongWork()
{
Debug.Assert(this.Dispatcher.CheckAccess() == false);
Thread.Sleep(1000);
}
Do Do()はUIコンテキストから通常呼び出されます。また、TaskSchedulerで定義されているShortUIWorkもそうです。しかし、LongWorkはUIスレッドでも呼び出されてしまいます。もちろん、これはUIをブロックします。
タスクがUIスレッドで実行されないようにするにはどうすればよいですか?
':
にかかわらず、あなたが戻ってデフォルトのタスクスケジューラに切り替えることで問題を回避することができます。 'LongWork'がUIスレッドをブロックしていることは確かですか? – Tigran
@Tigran:TPLは定義ではなく、デフォルトでバックグラウンドスレッドを使用します。 –
問題を再現しないコードは役に立ちません。このような動作の一般的な理由は、COMコンポーネントのラッパークラスです。 COMは、自動的にそれらを作成したスレッドにコールをマーシャリングすることによって、スレッドセーフであることをサポートしないように自分自身を宣言するクラスのオブジェクトを保持します。 –