2012-03-17 37 views
8

次のコードは、実際のアプリケーションのコードを単純化したものです。以下の問題は、長いスレッドがバックグラウンドスレッドではなく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スレッドで実行されないようにするにはどうすればよいですか?

+0

':

にかかわらず、あなたが戻ってデフォルトのタスクスケジューラに切り替えることで問題を回避することができます。 'LongWork'がUIスレッドをブロックしていることは確かですか? – Tigran

+2

@Tigran:TPLは定義ではなく、デフォルトでバックグラウンドスレッドを使用します。 –

+1

問題を再現しないコードは役に立ちません。このような動作の一般的な理由は、COMコンポーネントのラッパークラスです。 COMは、自動的にそれらを作成したスレッドにコールをマーシャリングすることによって、スレッドセーフであることをサポートしないように自分自身を宣言するクラスのオブジェクトを保持します。 –

答えて

8

LongRunningは、TaskSchedulerのヒントに過ぎません。 SynchronizationContextTaskSchedulerTaskScheduler.FromCurrentSynchronizationContext()によって返される)の場合、ヒントは明らかに無視されます。

一方で、これは直観に反しているようです。結局のところ、タスクが長時間実行されている場合は、UIスレッドで実行することはほとんどありません。 MSDNによれば一方、:

LongRunning - タスクは実行時間の長い、 粗粒操作することを指定。 TaskSchedulerには、 オーバーサブスクリプションが保証されるというヒントが提供されています。

UIスレッドは、スレッドプールのスレッド、NO「のオーバーサブスクリプション」(スレッドプールの枯渇)が発生することができないので、多少ヒントがSynchronizationContextTaskSchedulerには影響を及ぼさないであろうことが理にかなっているので。 * *定義によってUI上で実行されませんスレッドを作成tasks`

void ShortUIWork() 
{ 
    Debug.Assert(this.Dispatcher.CheckAccess() == true); 
    Task.Factory.StartNew(LongWork, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); 
} 
+0

UIスレッド上で実行されているのに、 'LongWork'の' Debug.Assert(this.Dispatcher.CheckAccess()== false); ' –

+0

@Branko:私は従いません。私の答えに応じてコードが変更された場合、UIスレッドでLongWorkは実行されません。そのため、アサーションは成功します(ただし、元のコードでは失敗します)。 –

+0

奇妙なことに、私は元々デバッグしたが、元のコードでは失敗してしまったと誓っていました。私はいくつかの奇妙なデバッガの相互作用(それが何であろうと)を打つか、これは私の一部の脳の失敗に過ぎません。 –

関連する問題