2012-08-31 8 views
5

Tôi đang làm việc trên ứng dụng WPF và tôi chỉ muốn thay đổi con trỏ trước và sau khi tác vụ chạy. Tôi có mã này:Tác vụ ContinueWith() Không cập nhật Con trỏ trên Giao diện Người dùng UI

this.Cursor = Cursors.Wait; 

Task.Factory.StartNew(() => PerformMigration(legacyTrackerIds)).ContinueWith(_ => this.Cursor = Cursors.Arrow); 

Con trỏ thực sự thay đổi con trỏ chờ nhưng không thay đổi về mũi tên khi hoàn thành công việc. Nếu tôi đặt một breakpoint trong phương thức ContinueWith(), nó sẽ bị tấn công. Nhưng con trỏ không thay đổi về mũi tên. Tại sao?

Đây là cách cũ tôi đã thử. Con trỏ đã thay đổi về mũi tên, nhưng tôi không muốn Wait() cho nhiệm vụ.

this.Cursor = Cursors.Wait; 

Task.Factory.StartNew(() => PerformMigration(legacyTrackerIds)).Wait(); 

this.Cursor = Cursors.Arrow; 

Trả lời

10

Cần thay đổi con trỏ trên chuỗi giao diện người dùng. Bạn có thể sử dụng các overload of ContinueWith mà phải mất một lịch trình nhiệm vụ:

var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 

Task.Factory 
    .StartNew(() => PerformMigration(legacyTrackerIds)) 
    .ContinueWith(_ => this.Cursor = Cursors.Arrow, uiScheduler); 

Hoặc sử dụng Dispatcher.Invoke phương pháp:

Task.Factory 
    .StartNew(() => PerformMigration(legacyTrackerIds)) 
    .ContinueWith(_ => { Dispatcher.Invoke(() => { this.Cursor = Cursors.Arrow; }); }); 
+0

Tôi không nên có ngoại lệ sau đó? –

+0

@BobHorn Bạn rất có thể là, nhưng vì nó trong một chủ đề nền nó chỉ đưa xuống chủ đề đó, chứ không phải toàn bộ ứng dụng. – Servy

+0

Khi tôi thử đề xuất đầu tiên, tôi nhận được lỗi biên dịch: 'Không thể chuyển đổi biểu thức lambda thành loại 'System.Delegate' vì nó không phải là loại đại biểu'. –

2

Tôi nghĩ rằng bạn cần phải sử dụng bối cảnh đồng bộ chính xác:

this.Cursor = Cursors.Wait; 

var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext()); 

Task.Factory.StartNew(() => PerformMigration(legacyTrackerIds)) 
      .ContinueWith(_ => this.Cursor = Cursors.Arrow, uiScheduler); 
2

Vấn đề là sự tiếp tục cần phải chạy trong chuỗi giao diện người dùng. Hiện tại nó đang được thực hiện trong một chủ đề nền.

Thêm TaskScheduler.FromCurrentSynchronizationContext() vào tham số thứ hai là ContinueWith để nó chạy trong chuỗi giao diện người dùng.