2011-09-14 21 views
12

bir WinForm iş parçacığı üzerinde ve gözlemlenebilir bir dizi kalkmak: Bu işe yaramazsanasıl böyle bir WinForm senkronizasyon bağlamı veya zamanlamasını bir winform uygulama var

Form form = new Form(); 
Label lb = new Label(); 
form.Controls.Add(lb); 

Observable.Interval(TimeSpan.FromSeconds(1)) 
      .Subscribe(l => lb.Text = l.ToString()); 

Application.Run(form); 

, l => lb.Text = l.ToString() çalıştırılamaz çünkü formu oluşturan ana iş parçacığı üzerinde, ancak bu iş parçacığı üzerinde nasıl çalıştırılacağını anlayamıyorum. Sanırım, IScheduler ya da SynchronizationContext alan bir IObservable.SubscribeOn kullanmalıyım, ancak ana iş parçacığının synchronizationcontext'i nasıl elde edeceğimi bilmiyorum ve bulabildiğim tek Zamanlayıcılargibi Scheduler.CurrentThread gibi statik özelliklerdi Immediate, NewThread, TaskPool ve ThreadPool, bunların hiçbiri işe yaramadı.

Rx sürümüm 1.0.10621'dir.

cevap

23

ben soru gönderebilir hemen sonra, ben çözüm bulmak:

Form form = new Form(); 
Label lb = new Label(); 
form.Controls.Add(lb); 

Observable.Interval(TimeSpan.FromSeconds(2)) 
      .ObserveOn(SynchronizationContext.Current) 
      .Subscribe(l => lb.Text = l.ToString()); 

Application.Run(form); 

This bağlantı yardımcı oldu. İki not:

  • Tüm parçacıkların bir eşitleme içeriği yoktur, ancak bir iş parçacığı üzerinde oluşturulan ilk form, bu iş parçacığı için bir eşitleme bağlamı ayarlayacaktır, böylece UI iş parçacığının her biri bir tane vardır.
  • Doğru yöntem, SubscribeOn değil ObserveOn değil. Şu anda, bunun nedenini bilmek için yeterli bilgim yok, bu yüzden yorumlardaki herhangi bir bağlantı takdir edilecektir.

düzenleme: this bağlantının ilk kısmına sayesinde, artık ObserveOn ve SubscribeOn arasındaki fark hakkında daha fazla anlıyoruz. Kısacası: Bu bağlamdan IObserver yöntemleri (OnNext ve arkadaşları) arayacak bir senkronizasyon bağlamına gözlemler

  • bir gözlemlenebilir. Örneğimde, ana/UI iş parçacığı üzerinde gözlemlerim, bu nedenle, bu nedenle bir çapraz iş parçacığı istisnası almazsınız
  • SubscribeOn biraz daha karmaşıktır, bu yüzden bir örnek: Concat gözlenebilir bir sayı alır ve onları uzun bir gözlemlenebilir ile birleştirir . Gözlemlenebilir bir OnCompleted numaralı telefon çağrıldığında, birleşik gözlemlenebilir bu aboneliği bertaraf edecek ve bir sonraki gözlemlenebilir üyeye abone olacaktır. Tüm bunlar, OnCompleted10 adlı iş parçacığı üzerinde gerçekleşir, ancak Observable.FromEvent tarafından oluşturulan gözlenebilir öğelere abone olmayla ilgili bazı sorunlar olabilir, ör. Bir işleyici işleyicisini UI iş parçacığından başka bir iş parçacığından eklerseniz Silverlight atar ve birden çok farklı iş parçacığından bir olay işleyicisini eklerseniz, WinForms ve WPF atanır. SubscribeOn, gözlenebilir kancaların altta yatan etkinliğe kadar olan parçayı kontrol etmenizi sağlar.
+7

'SubscribeOn' yalnızca gerçek aboneliğin hangi iş parçacığı olduğunu ayarlar, 'ObserveOn', 'OnNext' çağrılarının hangi iş parçacığının çalıştırılacağını belirler. Olaylarla karşılaştırmak için 'SubscribeOn', yalnızca ana iş parçacığına olay işleyicileri eklemenizi sağlamak gibidir, ancak' ObserveOn', olay işleme rutininin doğru iş parçacığına çağrıldığından emin olur. –

+0

@Gideon: Teşekkürler. Geliştirdiğim anlayışı yansıtmak için cevabımı düzenledim, ancak yorumlarınız bunu çok iyi özetliyor. – Boris

+2

Eğer System.Reactive.Windows.Forms.dll bir başvuru var .ObserveOn (form) yapabilir ve Control.Invoke eşdeğerini yapacaktır. –