2012-07-12 14 views
13

Her 100 milisaniyede bir yeni bir değer pompalayan bir rasgele sayılar eşzamansız akışı oluşturmak istiyorum. Eğer denemek ve bu çalıştırırsanız, sadece tekrar tekrar aynı değeri tekrar tutar fark edeceksiniz Gözlemlenebilir.Defer - tam olarak ne yaptığını açıklığa kavuşturmak gerekiyor

 var random = new Random(); 
     Observable.Start(() => random.Next()) 
        .Delay(TimeSpan.FromMilliseconds(100)) 
        .Repeat() 
        .Subscribe(Console.WriteLine); 

: çözüm ile gelip çalışırken, benim ilk girişimi böyle bir şey görünüyordu. Tamam, sanırım Repeat'in nasıl çalıştığını yanlış anladım. biraz etrafı oynadıktan sonra, ben bu geldi ve işe yaradı:

 var random = new Random(); 
     Observable.Defer(()=> Observable.Start(() => random.Next())) 
        .Delay(TimeSpan.FromMilliseconds(100)) 
        .Repeat() 
        .Subscribe(Console.WriteLine); 

Yani ertele aslında ne yaptığını anlamak için MSDN belgelerine gitti ve bu da diyor ki:

Yeni bir gözlemci abone olduğunda, gözlemlenebilir fabrika 'u çağıran gözlenebilir bir sekans döndürür. Benim kod örneğinde, ben sadece bir kere gözlemlenebilir abone ediyorum, öyleyse niye görünüşte defalarca Observable.Start(...) başlatıyordur:

benim karışıklık bu sanırım? Yoksa Repeat() yanlış anlaşılıyor muyum? Herhangi bir açıklama harika olurdu.

cevap

17

Yanlış anlıyorsunuz Tekrar ediyorum. Temel olarak, Repeat, her tamamlandığında, gözlemlenebilir bir şekilde yeniden yayınlamaya devam edecektir.

Gözlemlenebilir.Start, ilk kez Abone olarak adlandırdığınız anda değeri önbelleğe alır ve her abone olduğunuzda geri döner. İlk örnekte aynı sayıya neden olan budur.

IObservable<T> Defer(Func<IObservable<T>> factory) 
{ 
    return Observable.Create<T>(obs => factory().Subscribe(obs)); 
} 

böylece gözlemlenebilir Defer abone her zaman, factory işlevini çağırmalıdır:

ertele böyle bir şey çalışır. Bu durumda, fabrika yeni gözlemlenebilir oluşturur, böylece Start'un önbellekleme davranışından kaçınılır.

Tanımladığınız diziyi elde etmenin alternatif bir yolu, zamanlama ve Select numaranızı almak için Interval kullanmaktır.

Observable.Interval(TimeSpan.FromMilliseconds(100)) 
      .Select(i => random.Next()) 
      .Subscribe(Console.WriteLine); 
5

Rasgele sayıları "üretmek" için basit bir yol .Generate'u kullanmaktır. Bunu deneyin:

var rnd = new Random(); 

Observable 
    .Generate(
     0, 
     x => true, 
     x => x, 
     x => rnd.Next(), 
     x => TimeSpan.FromMilliseconds(100.0)) 
    .Subscribe(n => { }); 
İlgili konular