Во-первых, вместо метода буферизации, который вы использовали для обнаружения завершенной команды, я бы сделал что-то вроде этого. И вместо того, чтобы беспокоиться о создании команды для CommandB, я бы просто выполнил ее как метод. Вы по-прежнему можете использовать команду, если хотите, но в этом примере я буду использовать только асинхронный вызов. Я использую ExecuteUntilItYieldsTheSelectedComboBoxValue для непрерывного выполнения вашей логики CommandB в цикле, пока не будет найдено соответствующее значение. Он использует Observable.Create, поэтому вы можете контролировать, когда запускается OnNext. И вы можете пометить его тайм-аутом и обработать его в расширении подписки.
CommandA.IsExecuting
// IsExecuting has an initial value of false. We can skip that first value
.Skip(1)
// Filter until the executing state becomes false.
.Where(isExecuting => !isExecuting)
// Start an inner observable for your "CommandB" logic.
.Select(_ => ExecuteUntilItYieldsTheSelectedComboBoxValue())
// Whenever CommandA is invoked, dispose of the last inner observable subscription and resubscribe.
.Switch()
.Subscribe(
_ => Console.WriteLine("OnNext"),
ex => [display error message]);
...
private IObservable<Unit> ExecuteUntilItYieldsTheSelectedComboBoxValue()
{
return Observable
.Create<Unit>(
async o =>
{
int randNum = -1;
do
{
randNum = await GetRandomNumberAsync();
} while(randNum != ComboBoxValue);
o.OnNext(Unit.Default);
o.OnCompleted();
return Disposable.Empty;
})
.Timeout(TimeSpan.FromSeconds(3));
}
Обновить
Основываясь на том, что указала Enigmativity, о необходимости вернуть что-то лучшее, чем Disposable.Empty (чтобы отменить любую выполняемую асинхронную задачу и выйти из цикла), я изменяю метод ExecuteUntilItYieldsTheSelectedComboBoxValue следующим образом:
private IObservable<Unit> ExecuteUntilItYieldsTheSelectedComboBoxValue()
{
return Observable
// Call our async method and pass in a cancellation token.
.FromAsync(ct => GetRandomNumberAsync(ct))
// Keep generating random numbers.
.Repeat()
// Until we find one that matches the ComboBoxValue.
.Where(x => x == ComboBoxValue)
// Just take the first one so this inner observable will complete.
.Take(1)
.Select(_ => Unit.Default)
.Timeout(TimeSpan.FromSeconds(3));
}
Обратите внимание, что по-прежнему можно заставить метод Observable.Create работать правильно, но это отредактированное решение чище и менее подвержено ошибкам. Дайте знать, если у вас появятся вопросы.
person
Colt Bauman
schedule
20.06.2018