#linq-to-sql #system.reactive
#linq-to-sql #system.reactive
Вопрос:
Я пытаюсь узнать, как наилучшим образом использовать библиотеку реактивных расширений, и настроил простое тестовое приложение WPF для просмотра таблицы базы данных журнала. В классе ViewModel я заполняю an ObservableCollection
первыми 100 записями журнала из Linq to Sql DataContext
и пытаюсь использовать Rx, чтобы пользовательский интерфейс оставался отзывчивым.
Следующий фрагмент работает, если база данных недоступна, и в этот момент приложение выдает исключение и выходит из строя. Где было бы лучшее место для обработки исключений подключения к базе данных и почему они не обрабатываются OnError
методом наблюдателя?
ObservableCollection<LogEntry> _logEntries = new ObservableCollection<LogEntry>();
DataContext dataContext = new DataContext( "connection string" );
(from e in dataContext.LogEntries
select e).Take( 100 ).ToObservable()
.SubscribeOn( Scheduler.ThreadPool )
.ObserveOnDispatcher()
.Subscribe( _logEntries.Add, ex => System.Diagnostics.Debug.WriteLine( ex.ToString() ) );
Ответ №1:
Попробуйте это вместо ToObservable:
public static IObservable<T> SafeToObservable(this IEnumerable<T> This)
{
return Observable.Create(subj => {
try {
foreach(var v in This) {
subj.OnNext(v);
}
subj.OnCompleted();
} catch (Exception ex) {
subj.OnError(ex);
}
return Disposable.Empty;
});
}
В целом, однако, это не самое лучшее использование Rx, поскольку источник данных не очень легко Rx’идентифицировать — фактически, код выполнит большую часть работы в потоке пользовательского интерфейса, отправит его случайным рабочим потокам, а затем отправит обратно (т. Е. полностью потраченная впустую работа). Задача диспетчер.Здесь вам больше подойдет BeginInvoke.
Комментарии:
1. Спасибо, Пол, что-то подобное должно помочь, я надеялся, что существует какой-то существующий механизм для обработки ошибок во время создания Observable. Приведенный мной пример — это действительно урезанная версия, просто чтобы проиллюстрировать проблему. Фактический поиск данных включает в себя некоторый интервальный опрос и доступ к внешним ресурсам (немного больше Rx’y).
2. В какой момент исключения обычно передаются методу onError?
3. Если при перечислении последовательности произойдет исключение, оно будет передано в onError. Исключение, которое вы видите, сбой подключения к БД, возникает при вызове GetEnumerator. Логически это выходит за рамки последовательности (потому что ее даже нет), и исключение не обрабатывается Rx. Мое предложение состояло бы в том, чтобы обернуть ваш код в try / catch, чтобы разделить концепции, перечисляющие через данные, и попытки получить данные для перечисления.