2012-06-15 39 views
7

Tôi đang tìm cách triển khai một số hành vi điều chỉnh vào một trong các kiểu xem của tôi. Đó là một ứng dụng Silverlight, tuy nhiên tôi không nghĩ điều đó đặc biệt quan trọng.Điều chỉnh/xếp hàng sự kiện - Tiện ích mở rộng phản ứng?

Hãy xem xét một lớp học với ba đặc tính:

  • Property1
  • Property2
  • Property3

Bất cứ khi nào một trong những thuộc tính được cập nhật, làm mới là cần thiết.

private void Refresh() 
{ 
    //Call out to the server, do something when it comes back 
} 

Mục tiêu của tôi là như sau:

  • Nếu một Refresh đang diễn ra, chúng tôi lý tưởng nên hủy bỏ các cuộc gọi đến máy chủ, và đưa ra một yêu cầu mới
  • Nếu một tài sản được thay đổi, chúng ta nên để lại một số cửa sổ nhỏ thời gian (có lẽ là 0,1 giây), nơi chúng ta chờ đợi những thay đổi bổ sung. Bằng cách này, nếu nhiều thuộc tính được thay đổi nhanh chóng (ví dụ, theo chương trình), chúng tôi không gửi spam máy chủ với các yêu cầu. Sẽ ổn cho cửa sổ thứ hai 0,1 để đặt lại trên mỗi thay đổi, nhưng không bắt buộc.

Nếu có vấn đề, tôi đang sử dụng triển khai ChannelFactory cho cuộc gọi máy chủ.

Tôi có thể sử dụng loại mẫu nào để thực hiện việc này? Đây có phải là một cái gì đó phản ứng mở rộng có thể giúp tôi với?

Edit:

đánh dấu câu trả lời của Paul là chính xác. Trong khi ReactiveUI hiện không hoạt động với Silverlight5, nó nêu rõ các bước tiếp cận/thành phần để giải quyết vấn đề bằng cách sử dụng Rx.

+1

Rx chắc chắn hỗ trợ này, xem http://rxwiki.wikidot.com/101samples#toc29 - về việc hủy nó - hãy nhìn vào CancellationToken từ Nhiệm vụ –

Trả lời

6

Đây là cách bạn sẽ làm điều này với ReactiveUI:

IObservable<TheData> FetchNewData() 
{ 
    // TODO: Implement me 
} 

this.WhenAny(x => x.Property1, x => x.Property2, x => x.Property3, (x,y,z) => Unit.Default) 
    .Throttle(TimeSpan.FromMilliseconds(200), RxApp.DeferredScheduler) 
    .Select(x => FetchNewData()) 
    .Switch() // We only care about the req corresp. to latest values of Prop1-3 
    .ToProperty(this, x => x.Data); 

Cập nhật: Dưới đây là làm thế nào để đảm bảo rằng chỉ có một chạy cùng một lúc, với sự báo trước rằng bạn có thể nhận out-of-trật tự các kết quả.

this.WhenAny(x => x.Property1, x => x.Property2, x => x.Property3, (x,y,z) => Unit.Default) 
    .Throttle(TimeSpan.FromMilliseconds(200), RxApp.DeferredScheduler) 
    .Select(_ => Observable.Defer(() => FetchNewData())) 
    .Merge(1) 
    .ToProperty(this, x => x.Data); 

Các hành vi bạn mô tả, trên thực tế sẽ có lẽ không desireable, vì nếu tài sản tiếp tục thay đổi, bạn sẽ kết thúc với một danh sách các yêu cầu cũ để phát hành - bạn có thể tối ưu hóa này nếu bạn đã thực hiện một cái gì đó giống như một "BufferingSwitch()" nhà điều hành đã không trả lại kết quả của nó cho đến khi nó đã chắc chắn không có thay đổi - đó thực sự là mát mẻ để viết.

đạo đức của câu chuyện, async là phức tạp ™ :)

+0

Cảm ơn, trông giống như những gì tôi cần ở cái nhìn đầu tiên. Đây có phải là hợp lệ cho silverlight? Tôi không thể tìm thấy phương pháp mở rộng WhenAny để thử. –

+0

@ShaunRowan: Phần mở rộng đó là từ ReactiveUI (http://www.reactiveui.net). Các phiên bản trước (v2) hỗ trợ Silverlight. Phiên bản hiện tại (v3) thì không. Đặc biệt nếu bạn đang làm MVVM, đây là một thư viện thực sự tuyệt vời. –

+0

Cảm ơn, tôi sẽ kiểm tra! Đối với một số lý do bộ não của tôi chỉ trao đổi "ReactiveUI" với "phần mở rộng phản ứng". (Tôi không biết thư viện.) –

Các vấn đề liên quan