Feels like bugs and problems are attracted to me lately! =P
So I finally took some time off today to explore a little Rx.
Heres what I did:
Here's the only piece of running code:
private void button1_Click(object sender, EventArgs e)
{
var txtc = Observable.FromEvent<EventArgs>(textBox1, "TextChanged")
.Throttle(TimeSpan.FromSeconds(0.5))
.SubscribeOnDispatcher();//**also tried .SubscribeOn(this)
var t = from x in txtc select textBox1.Text;
t.Subscribe(x => listBox1.Items.Add(x));
}
Now, when run Debug (F5) I click the Button, all good, I then type something, poof! The form just silently dies!!
If I run without debugging, the application runs flawlessly!
Note: I removed the code from the Form.Load event because of the known bug with VS not breaking on exceptions in that event on Win7x64 (and yes thats my machine)
This is what the debug output looks like:
The thread 'vshost.NotifyLoad' (0x1438) has exited with code 0 (0x0).
The thread 'vshost.LoadReference' (0x155c) has exited with code 0 (0x0).
'RxWinForms.vshost.exe' (Managed (v4.0.30319)): Loaded '\RxWinForms\bin\Debug\RxWinForms.exe', Symbols loaded.
A first chance exception of type 'System.InvalidOperationException' occurred in System开发者_运维问答.Windows.Forms.dll
The program '[5228] RxWinForms.vshost.exe: Managed (v4.0.30319)' has exited with code 0 (0x0).
The program '[5228] RxWinForms.vshost.exe: Program Trace' has exited with code 0 (0x0).
You need to make sure that either the Throttling is happening on the current dispatcher or that you switch back on to the current dispatcher through ObserveOn (not SubscribeOn) before you try and change the UI (I believe that by default Throttling is done on the TaskPool).
So both of the solutions below work:
private void button1_Click(object sender, EventArgs e)
{
txtc = Observable.FromEvent<EventArgs>(textBox1, "TextChanged")
.Throttle(TimeSpan.FromSeconds(0.5))
.ObserveOn(Scheduler.Dispatcher);
var t = from x in txtc
select textBox1.Text;
t.Subscribe(x => listBox1.Items.Add(x));
}
and
private void button1_Click(object sender, EventArgs e)
{
txtc = Observable.FromEvent<EventArgs>(textBox1, "TextChanged")
.Throttle(TimeSpan.FromSeconds(0.5), Scheduler.Dispatcher)
var t = from x in txtc
select textBox1.Text;
t.Subscribe(x => listBox1.Items.Add(x));
}
James is correct. However, it is recommended that you use the IScheduler
overload of methods (like Throttle
, rather than using the default overload and then using ObserveOn
(which will cause it to jump to the task pool and then back to the dispatcher).
精彩评论