простой код rx молча терпит неудачу в формах Windows только во время отладки в Visual Studio 2010

Такое ощущение, что в последнее время меня привлекают баги и проблемы! =П

Итак, сегодня я, наконец, взял немного свободного времени, чтобы изучить немного Rx.

Вот что я сделал:

альтернативный текст

Вот единственный кусок работающего кода:

 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));
 }

Теперь, когда я запускаю Debug (F5), я нажимаю кнопку, все хорошо, затем я что-то набираю, пуф! Форма просто молча умирает!!

Если я запускаю без отладки, приложение работает безупречно!

Примечание. Я удалил код из события Form.Load из-за известной ошибки, из-за которой VS не прерывал исключения в этом событии на Win7x64 (и да, это моя машина)

Вот как выглядит вывод отладки:

Поток vshost.NotifyLoad (0x1438) завершился с кодом 0 (0x0).

Поток vshost.LoadReference (0x155c) завершился с кодом 0 (0x0).

«RxWinForms.vshost.exe» (управляемый (v4.0.30319)): загружен «\RxWinForms\bin\Debug\RxWinForms.exe», символы загружены.

Возникло первое случайное исключение типа «System.InvalidOperationException» в System.Windows.Forms.dll.

Программа «[5228] RxWinForms.vshost.exe: Managed (v4.0.30319)» завершилась с кодом 0 (0x0).

Программа «[5228] RxWinForms.vshost.exe: трассировка программы» завершилась с кодом 0 (0x0).


person gideon    schedule 11.01.2011    source источник


Ответы (2)


Вы должны убедиться, что либо регулирование происходит в текущем диспетчере, либо что вы снова переключаетесь на текущий диспетчер через ObserveOn (не SubscribeOn), прежде чем пытаться изменить пользовательский интерфейс (я считаю, что по умолчанию регулирование выполняется в TaskPool). ).

Итак, оба приведенных ниже решения работают:

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));
}

и

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));
}
person James Hay    schedule 11.01.2011
comment
+1 Отлично, я думал, что столкнулся с проблемой! Скажите, что делает SubscribeOnDispatcher()? Кажется немного раздражающим, так как во многих примерах используется SubscribeOnDispatcher() . - person gideon; 11.01.2011
comment
@giddy В маловероятном случае, когда наблюдаемый источник (который реализует IObservable) блокируется во время вызова Subscribe(), вы можете использовать SubscribeOn, чтобы убедиться, что это не так. - person James Hay; 11.01.2011
comment
спасибо=) Понятно... так что же на самом деле делает SubscribeOnDispatcher()? Я делаю вызов как SubscribeOnDispatcher(), так и SubscribeOn Или мой исходный код был частично неправильным? (Поскольку я понял это из примера с серебряным светом) - person gideon; 11.01.2011
comment
@giddy SubscribeOn (и SubscribeOnDispatcher, который является просто вызовом SubscribeOn, проходящим в Scheduler.Dispatcher) заключает ваш вызов Subscribe() в scheduler.Schedule(() => originalSource.Subscribe()). Он используется в том редком случае, когда наблюдаемый объект блокируется во время вызова Subscribe. - person James Hay; 11.01.2011

Джеймс прав. Однако рекомендуется использовать перегрузку методов IScheduler (например, Throttle, а не использовать перегрузку по умолчанию, а затем использовать ObserveOn (что приведет к переходу к пулу задач, а затем обратно к диспетчеру).

person Richard Szalay    schedule 11.01.2011