2011-11-10 54 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()