Недавно я столкнулся с ситуацией, когда было бы выгодно иметь асинхронную операцию, представленную как Task<T>
, так и IObservable<T>
. Представление задачи поддерживает состояние операции (IsCompleted
, IsFaulted
и т. д.), в то время как наблюдаемое представление позволяет интересным образом комбинировать несколько операций (Concat
, Merge
, Switch
и т. д.), автоматически обрабатывая отмену любой операции, подписка на которую была отменена. кстати, решая таким образом проблему незабытых асинхронных операций. Поэтому меня заинтересовали способы объединения этих двух представлений.
Простым и, вероятно, правильным способом их объединения была бы композиция: создание типа, который хранит внутри Task<T>
и IObservable<T>
и предоставляет их как два своих свойства. Но в этом вопросе меня интересует сложная и, вероятно, непрактичная возможность типа, который является Task<T>
и является IObservable<T>
одновременно. Тип, который можно передать напрямую API-интерфейсам, которые принимают либо задачи, либо наблюдаемые объекты, и в любом случае делают правильные вещи. Так что это не может быть просто объект, похожий на задачу. Он должен наследоваться от реального объекта, самого класса Task<T>
. Что-то вроде этого:
public class AsyncOperation<TResult> : Task<TResult>, IObservable<TResult>
{
public AsyncOperation(Func<CancellationToken, Task<TResult>> action)
{
//...
}
}
Создание экземпляра AsyncOperation
должно немедленно вызвать указанное действие. Другими словами, AsyncOperation
должно представлять комбинацию горячих задач/наблюдаемых.
Можно ли создать такой тип?
Кстати, вот тема в библиотеке ReactiveX/RxJava, которая доказывает, что другие уже думали об этой проблеме раньше: Нет методов isCompleted или isErrored в Observable
Task<T>
не выглядит проблематичным (это неsealed
), но, может быть, вы можете написать, в чем проблема (желательно с MCVE). - person Progman   schedule 14.11.2020Task<T>
создают задачи делегирования, а асинхронный метод создает задачу в стиле обещания. Конструкторы, связанные с задачами в стиле обещаний, являются частными или внутренними. - person Theodor Zoulias   schedule 14.11.2020IObservable<T>
, например возвращаемое значение методаObservable.StartAsync
, не наследуются от классаTask<T>
. Поэтому я не могу использовать функциональность задачи для наблюдаемого, представляющего одну асинхронную операцию. И этот функционал нужен в некоторых сценариях. Например, поток выполнения может зависеть от того, успешно ли завершена операция или нет. - person Theodor Zoulias   schedule 15.11.2020Observable.StartAsync
вызывает внутри метод расширенияTask.ToObservable
, который возвращает упакованный экземпляр внутреннегоSlowTaskObservable
. Этот класс хранит базовую задачу, созданную при вызовеObservable.StartAsync
, но у меня нет никакого способа получить эту задачу (кроме использования приемов отражения). Моя проблема не существовала бы, если бы эта задача была доступна! - person Theodor Zoulias   schedule 16.11.2020