2011-08-15 6 views
8

Tôi có một lớp học,Tạo một wrapper thể quan sát được cho một tổ chức phi chủ đề lớp an toàn

public class Test 
{ 
    public int Calc(); 
} 

mà yêu cầu tất cả các cuộc gọi đến Calc được thực hiện trên các chủ đề tương tự như một trong những ngày mà thử nghiệm đã được tạo ra. Tôi cần tạo Test một lần (hoạt động tốn kém) và gọi Calc nhiều lần.

Tôi muốn có một wrapper mà sẽ cho phép tôi gọi Calc asynchronousely:

public class TestWrapper 
{ 
    private Test _test; 
    public IObservable<int> Calc(); 
} 

Một cách để làm điều đó sẽ tạo ra một BackgroundWorker hoặc một chủ đề và sử dụng nó như là một sự đảm bảo rằng tất cả các hoạt động vào Kiểm tra nằm trên cùng một chuỗi. Để đơn giản, chúng ta có thể giả định rằng tất cả các cuộc gọi đến Calc() sẽ được thực thi tuần tự, do đó không cần phải lo lắng về việc xếp hàng.

Có cách nào RX thanh lịch hơn để làm điều đó không?

Trả lời

4

Nếu nó có thể cho Test được tạo ra khi TestWrapper được tạo ra sau đó lớp này dường như để đáp ứng yêu cầu của bạn:

public class TestWrapper 
{ 
    public TestWrapper(Func<Test> factory) 
    { 
     _scheduler = new EventLoopScheduler(); 
     _test = Observable.Start(factory, _scheduler).First(); 
    } 

    private readonly EventLoopScheduler _scheduler; 
    private readonly Test _test; 

    public IObservable<int> Calc() 
    { 
     return Observable.Start(() => _test.Calc(), _scheduler); 
    } 
} 

Nó được sử dụng như sau:

var testWrapper = new TestWrapper(() => new Test()); 
testWrapper.Calc().Subscribe(x => { }); 

tôi đã thử nghiệm nó và nó tạo ra Test trên cùng một luồng mà Calc được thực hiện trên. Mặt khác, đăng ký được xử lý trên cùng một chuỗi với chính bản thân số testWrapper được tạo trên (tức là chuỗi cuộc gọi).

0

sử dụng lớp ThreadLocal<T> khi tạo bạn thể hiện của Test:

var MyTEST = new ThreadLocal<Test>(); 

sau đó bạn có thể sử dụng MyTEST.Value.Calc() cho bất kỳ cuộc gọi ...

Một lựa chọn khác là sử dụng đặt [ThreadStatic] trên thành viên thử nghiệm của lớp bao bọc ... xem http://msdn.microsoft.com/en-us/library/system.threadstaticattribute.aspx

Tùy thuộc vào việc bạn cần nhiều hơn một trường hợp Test bạn có thể làm cho nó một Singleton.

3

Vì vậy, từ nhận xét và đọc lại câu hỏi của bạn, tôi thu thập bạn muốn liên tục gọi hàm Calc() trên một chuỗi liên tục và có kết quả trả về là IObservable<Int>()?

Trong trường hợp này, tôi muốn sử dụng Observable.Create để bọc lớp TestEventLoopScheduler để đảm bảo lời gọi đến Calc nằm trên một chuỗi duy nhất.

public class TestWrapper 
{ 
    private Test _test; 
    public IObservable<int> Calc() 
    { 
    return Observable.Create(obsvr => 
    { 
     var fixedThreadsched = new EventLoopScheduler(); 
     var disp = new BooleanDisposable(); 
     while (!disp.IsDisposed) 
     { 
      fixedThreadsched.Schedule(() => obsvr.OnNext(_test.Calc())); 
     } 

     return disp; 
    }); 
    } 
} 
+0

Cảm ơn, EventLoopScheduler là chìa khóa để sắp xếp các cuộc gọi đến cùng một chuỗi. Tuy nhiên, câu trả lời này không giải thích làm thế nào để chuyển đổi từ TestWrapper.Calc mà sẽ được thực hiện trên thread UI để test.Calc ... –

+0

@Sergey - Cập nhật dựa trên ý kiến ​​của bạn –

+0

Điều này gần hơn ... Phần thiếu là bạn không tạo _test (nên được thực hiện trên EventLoopScheduler). Hmm ... Khó quyết định - bạn là người đầu tiên có EventLoopScheduler nhưng @enigmativity đã cung cấp câu trả lời đúng. Cảm ơn các bạn cả hai đều đá! –