/// <summary> /// Requests the last event for the specified event type and symbol. /// This method works only for event types that implement <see cref="IDxLastingEvent"/> /// marker interface. /// This method requests the data from the the uplink data provider, creates new event /// of the specified event type <c>E</c>, and completes the resulting promise with /// this event. /// </summary> /// <remarks> /// <para> /// This method is designed for retrieval of a snapshot only. /// Use <see cref="DXFeedSubscription{E}"/> if you need event updates in real time. /// </para> /// <para> /// The promise is <see cref="TaskStatus.Canceled"/> when the the underlying /// <see cref="DXEndpoint"/> is <see cref="DXEndpoint.Close()"/>. /// If the event is not available for any transient reason (no subscription, no /// connection to uplink, etc), then the resulting promise completes when the issue /// is resolved, which may involve an arbitrarily long wait. /// Use <see cref="CancellationTokenSource"/> class constructors and methods to /// specify timeout while waiting for promise to complete. /// If the event is permanently not available (not supported), then the promise /// completes exceptionally with <see cref="AggregateException"/>. /// </para> /// <para> /// There is a bulk version of this method that works much faster for a single event /// type and multiple symbols. /// See <see cref="GetLastEventsPromises{E}(ICollection{object}, CancellationToken)"/>. /// </para> /// <para> /// Note, that this method does not work when <see cref="DXEndpoint"/> was created /// with DXEndpoint.Role#STREAM_FEED role (promise completes /// exceptionally). /// </para> /// <para>Threads</para> /// <para> /// Use <see cref="Task.ContinueWith(Action{Task})"/> method on the resulting /// promise to receive notification when the promise becomes done. /// </para> /// </remarks> /// <example> /// Use the following pattern of code to acquire multiple events (either for multiple /// symbols and/or multiple events) and wait with a single timeout for all of them: /// <code> /// List<Task<LastingEvent>> promises = new List<Task<LastingEvent>>(); /// // iterate the following line for all events and/or symbols that are needed /// promises.Add(feed.GetLastEventPromise<eventType>(symbol, new CancellationTokenSource(taskTimeout).Token)); /// // combine the list of promises into one with Task utility method and wait /// try /// { /// Task.WaitAll(tasks.ToArray()); /// } /// catch (AggregateException) {} /// // now iterate the promises to retrieve results /// foreach (Task<LastingEvent> promise in promises) /// // result received exceptionally if this event was not found /// // so first check that task completes successfully /// if (promise.Status == TaskStatus.RanToCompletion) /// doSomethingWith(promise.Result); /// </code> /// </example> /// <typeparam name="E">The event type.</typeparam> /// <param name="symbol">The symbol.</param> /// <param name="cancellationToken">The task cancellation token.</param> /// <returns>The promise for the result of the request.</returns> /// <exception cref="ArgumentException"> /// The <paramref name="symbol"/> symbol is not one of string or <see cref= "CandleSymbol"/>. /// </exception > /// <exception cref="ArgumentNullException">The <paramref name="symbol"/> is null.</exception> public async Task <IDxLastingEvent> GetLastEventPromise <E>(object symbol, CancellationToken cancellationToken) where E : class, IDxLastingEvent { MarketEventSymbols.ValidateSymbol(symbol); return(await Task.Run(() => { if (endpoint.State == DXEndpointState.Closed) { throw new OperationCanceledException("Endpoint was been closed."); } LastingEventsCollector <E> collector = new LastingEventsCollector <E>(); IDXFeedSubscription <E> s = CreateSubscription <E>(); s.AddSymbols(symbol); s.AddEventListener(collector); while (!collector.HasEvent <E>(symbol)) { if (endpoint.State == DXEndpointState.Closed) { throw new OperationCanceledException("Endpoint was been closed."); } cancellationToken.ThrowIfCancellationRequested(); } return collector.GetEvent <E>(symbol); }, cancellationToken)); }
private async Task <List <E> > FetchOrSubscribeFromHistory <E>(object symbol, long fromTime, long toTime, IndexedEventSource source, CancellationToken cancellationToken) where E : IDxIndexedEvent { MarketEventSymbols.ValidateSymbol(symbol); return(await Task.Run(() => { if (endpoint.State == DXEndpointState.Closed) { throw new OperationCanceledException("Endpoint was been closed."); } HistoryEventsCollector <E> collector = new HistoryEventsCollector <E>(fromTime, toTime); IDXFeedSubscription <E> s = CreateSnapshotSubscription <E>(fromTime, source); s.AddEventListener(collector); s.AddSymbols(symbol); try { while (!collector.IsDone) { if (endpoint.State == DXEndpointState.Closed) { throw new OperationCanceledException("Endpoint was been closed."); } cancellationToken.ThrowIfCancellationRequested(); } } finally { /*Note: it is necessary i.e. new snapshot with similar type and symbol cannot * be created while this is not closed.*/ s.Close(); } List <E> eventsList = collector.Events; eventsList.Reverse(); return eventsList; }, cancellationToken)); }