2011-11-10 5 views
18

Tôi đã có mã trong một ViewModel gọi một dịch vụ thông qua một nhiệm vụ. Khi tác vụ kết thúc, nó sẽ điền một ObservableCollection. Vấn đề là nó đang chờ nhiệm vụ hoàn thành bằng cách sử dụng phương thức ContinueWith và cung cấp TaskScheduler.FromCurrentSynchronizationContext làm công cụ lập lịch tác vụ, để OC được cập nhật trên chuỗi giao diện người dùng.TaskScheduler.FromCurrentSynchronizationContext - cách sử dụng chuỗi điều phối WPF khi thử nghiệm đơn vị

Cho đến nay rất tốt, nhưng khi nói đến thử nghiệm đơn vị, nó ném một ngoại lệ nói rằng "SynchronizationContext hiện tại có thể không được sử dụng như một TaskScheduler." Nếu tôi sử dụng một SynchronizationContext giả thử nghiệm đơn vị, sau đó ObservableCollection ném một lỗi bởi vì nó đang được cập nhật dựa trên chủ đề điều phối.

Có cách nào để giải quyết vấn đề này không?

Cảm ơn.

Trả lời

17

Nó không phải là chính xác dễ dàng, nhưng nó không thực sự là khó. Những gì bạn cần làm là một spin lên một công nhân Chủ đề đó là thiết lập như STA và bạn bắt đầu lên thời gian chạy Dispatcher trên nó. Một khi bạn có nhân viên đó ngồi ở đó, bạn có thể gửi công việc đến nó từ các chủ đề thử nghiệm đơn vị, rõ ràng, không được khởi tạo cho loại công việc này. Vì vậy, trước hết, đây là cách bạn khởi động thread phối trong thiết lập thử nghiệm của bạn:

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(); 

Bây giờ, nếu bạn muốn sạch đóng thread xuống dọn dẹp thử nghiệm của bạn, mà tôi khuyên bạn làm thế, bạn chỉ cần làm như sau :

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

Vì vậy, tất cả những thứ cơ sở hạ tầng trên đường đi, đây là tất cả những gì bạn cần làm trong bài kiểm tra để thực thi trên chuỗi đó.

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

Nó hoạt động, cảm ơn bạn rất nhiều! – Alberto

14

Thêm này để khởi động thử nghiệm của bạn, để tạo ra một bối cảnh:

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

Có, điều này đã khắc phục được sự cố. Cảm ơn. –

0

Điều này làm cho nó thậm chí còn đơn giản hơn

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

bạn mã có thể sau đó sử dụng scheduler một cách rõ ràng (khởi tạo với TaskScheduler.FromCurrentSynchronizationContext() trong thời gian chạy)