2011-11-10 12 views
18

タスクを介してサービスを呼び出すViewModelにコードがあります。 タスクが終了すると、ObservableCollectionが読み込まれます。 問題は、ContinueWithメソッドを使用してTaskScheduler.FromCurrentSynchronizationContextをタスクスケジューラとして提供することでタスクが完了するのを待っているため、OCがUIスレッドで更新されることです。TaskScheduler.FromCurrentSynchronizationContext - 単体テスト時にWPFディスパッチャスレッドを使用する方法

これまでのところ、単体テストの場合、「現在のSynchronizationContextはTaskSchedulerとして使用できません」という例外がスローされます。 ユニットテストで模擬SynchronizationContextを使用すると、ObservableCollectionはディスパッチャスレッドに基づいて更新されているため、エラーをスローします。

これを回避する方法はありますか?

ありがとうございました。

答えて

17

厳密には簡単ではありませんが、それほど難しいことでもありません。あなたがする必要があるのは、STAとしてセットアップされたワーカースレッドをスピンアップし、その上でDispatcherランタイムを起動することです。あなたがそこに座っているワーカーをいったん持っていれば、明らかにこの種の作業のために初期化されていない単体テストスレッドから作業をディスパッチできます。だから、まず、ここでは、あなたのテストのセットアップでディスパッチャスレッドを起動方法は次のとおりです。

this.dispatcherThread = new Thread(() => 
{ 
    // This is here just to force the dispatcher infrastructure to be setup on this thread 
    Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => 
    { 
     Trace.WriteLine("Dispatcher worker thread started."); 
    })); 

    // Run the dispatcher so it starts processing the message loop 
    Dispatcher.Run(); 
}); 

this.dispatcherThread.SetApartmentState(ApartmentState.STA); 
this.dispatcherThread.IsBackground = true; 
this.dispatcherThread.Start(); 

、あなたはきれいに私はあなたがお勧めテストクリーンアップ、中にそのスレッドをシャットダウンしたい場合、あなたは、単に次の操作を行います:

Dispatcher.FromThread(this.dispatcherThread).InvokeShutdown(); 

このように、すべてのインフラストラクチャが邪魔になりません。テストでは、このスレッドで実行する必要があります。

public void MyTestMethod 
{ 
    // Kick the test off on the dispatcher worker thread synchronously which will block until the work is competed 
    Dispatcher.FromThread(this.dispatcherThread).Invoke(new Action(() => 
    { 
     // FromCurrentSynchronizationContext will now resolve to the dispatcher thread here 
    })); 
} 
+1

それは働いて、ありがとう! – Alberto

14

コンテキストを作成し、テストの初期化にこれを追加します。

SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); 
+0

はい、これで問題は解決しました。ありがとう。 –

0

これは、それがさらに簡単になり

TaskScheduler scheduler = Dispatcher.CurrentDispatcher.Invoke(TaskScheduler.FromCurrentSynchronizationContext)

あなたは、コードを明示的(初期化schedulerを使用することができます実行時にTaskScheduler.FromCurrentSynchronizationContext()

関連する問題