Ach wie schön und einfach kann das Leben doch sein, wenn ich einmal Ruhe zum Nachdenken habe! Vielleicht ist meine Lösung für andere Rx-Einsteiger ja auch interessant.
Nur mit diesem subscriptions-Array bin ich unzufrieden. Das ist eine Krücke. Hat jemand eine bessere Idee wie ich "access to modified closure" verhindern kann (zweiter Code-Block, im Button2Click-Eventhandler)?
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Threading;
namespace ControlInvokationRxStyle
{
internal static class ColorWorker
{
internal static bool Trigger;
internal static IObservable<Color> GetColdColorStream()
{
return Observable.Create<Color>(
color =>
{
while(Trigger)
{
color.OnNext(Color.LimeGreen);
Thread.Sleep(500);
color.OnNext(Color.BlueViolet);
Thread.Sleep(500);
}
return () => { };
});
}
// Ohne RefCount IConnectableObservable.
internal static IObservable<Color> HotColorStream()
{
var timerHook = Observable.Interval(TimeSpan.FromMilliseconds(500));
return Observable.Create<Color>(
color =>
{
timerHook.Subscribe(x => color.OnNext(x % 2 != 0
? Color.LimeGreen
: Color.BlueViolet));
return () => { };
})
// Note: Just for demonstration --->|
.Do(color => Debug.WriteLine("Publishing {0}", color.ToString()))
//|<---
.Publish()
.RefCount();
}
}
}using System;
using System.Concurrency;
using System.Disposables;
using System.Linq;
using System.Windows.Forms;
namespace ControlInvokationRxStyle
{
public partial class Form1 : Form
{
private readonly ControlScheduler led1Scheduler;
private readonly ControlScheduler led2Scheduler;
private bool connect;
public Form1()
{
InitializeComponent();
FormBorderStyle = FormBorderStyle.Fixed3D;
MaximizeBox = false;
SizeGripStyle = SizeGripStyle.Hide;
led1Scheduler = new ControlScheduler(LED1);
led2Scheduler = new ControlScheduler(LED2);
connect = false;
}
private void Button1Click(object sender, EventArgs e)
{
ColorWorker.Trigger = !ColorWorker.Trigger;
var stream = ColorWorker.GetColdColorStream();
stream.SubscribeOn(Scheduler.NewThread)
.ObserveOn(led1Scheduler)
.Subscribe(color => LED1.BackColor = color);
}
private void Button2Click(object sender, EventArgs e)
{
connect = !connect;
if(!connect)
return;
var stream = ColorWorker.HotColorStream();
IDisposable[] subscriptions = { Disposable.Empty };
/* Note: Zugriff über Array-Element um "access to modified
* closure" zu verhindern. */
subscriptions[0] = stream.SubscribeOn(Scheduler.NewThread)
.ObserveOn(led2Scheduler)
.Subscribe(color =>
{
LED2.BackColor = color;
if(!connect)
subscriptions[0].Dispose();
});
// Wird durch den Einsatz von RefCount nicht benötigt:
//stream.Connect();
}
}
}