//todo - если соединение быстрое то загрузка происходит так быстро что элементы управления мигают //черная магия будь бдителен все обработчики живут дольше чем форма и могут быть вызваны после того как форма была закрыта //или с новой копией этой формы если человек ушел а затем вернулся public virtual IEnumerable <IResult> Download(Loadable loadable) { loadable.IsDownloading = true; loadable.Session = Session; loadable.Entry = Session.GetSessionImplementation().PersistenceContext.GetEntry(loadable); var result = ObserveLoad(loadable); var disposable = new CompositeDisposable(3) { Disposable.Create(() => Bus.SendMessage(loadable, "completed")) }; var progress = result.Item1 .ObserveOn(UiScheduler) .Subscribe(p => loadable.Progress = p.EventArgs.ProgressPercentage / 100d); disposable.Add(progress); Log.Debug($"Загрузка {loadable}"); var download = result.Item2 .ObserveOn(Scheduler) .SelectMany(s => Extract(s, urn => loadable.GetLocalFilename(urn, Shell.Config)).ToObservable()) .ObserveOn(UiScheduler) .Subscribe(name => { Log.Debug($"Успешно загружен {loadable}"); var notification = ""; SessionGaurd(loadable.Session, loadable, (s, a) => { var record = a.UpdateLocalFile(name); s.Save(record); Bus.SendMessage(record); notification = $"Файл '{record.Name}' загружен"; if (IsActive) { Open(a).ToObservable().CatchSubscribe(r => ResultsSink.OnNext(r)); } }); Shell.Notifications.OnNext(notification); }, e => { Log.Debug($"Ошибка во время загрузки {loadable}", e); SessionGaurd(loadable.Session, loadable, (s, a) => a.Error(e)); }, () => { //если loadable.IsDownloaded = true то значит запрос дал результаты //и состояние сохранено в обработчике он next не нужны обращаться к базе нужно просто освободить ресурсы //если ничего не было найдено то нужно открыть сессию что сохранить состояние объекта if (loadable.IsDownloaded) { loadable.Completed(); } else { SessionGaurd(loadable.Session, loadable, (s, a) => a.Completed()); } }); disposable.Add(download); loadable.RequstCancellation = disposable; Bus.SendMessage(loadable); return(Enumerable.Empty <IResult>()); }