It seems like the entire update functionality of an NT8 bars request depends on all indicator OnBarUpdate methods completing quickly.
Here's a "deadlock indicator" for you, along with a comment that shows how to "fix" the deadlock (until further complications arise, as explained below)
using NinjaTrader.Data; using NinjaTrader.Gui; using System.Threading; using System.Windows.Media; namespace NinjaTrader.NinjaScript.Indicators { public class DeadlockIndicator : Indicator { readonly ManualResetEvent DataLoaded = new ManualResetEvent(false); BarsRequest Request; protected override void OnStateChange() { switch (State) { case State.SetDefaults: IsOverlay = false; AddPlot(new Stroke(Brushes.Orange), PlotStyle.Bar, "Value"); break; case State.DataLoaded: { Request = new BarsRequest(Instrument, Bars.FromDate, Bars.ToDate) { TradingHours = TradingHours, BarsPeriod = new BarsPeriod { BarsPeriodType = BarsPeriodType.Tick, Value = 1 }, }; Request.Request((_, errorCode, message) => { DataLoaded.Set(); }); /// Uncommenting this line will "fix" the deadlock /// by allowing the request to complete before the indicator starts processing OnBarUpdate events //DataLoaded.WaitOne(); break; } case State.Terminated: Request?.Dispose(); break; } } protected override void OnBarUpdate() { // Oops. Blocking the thread here prevents the bars request from completing. DataLoaded.WaitOne(); // Do stuff with the data from the bars request Value[0] = 1; } } }
But, I'm trying to make OnBarUpdate wait for the data to be available because 3rd party indicators, indicators that use my indicators, don't know about the asynchronous data and they want to be able to access my calculated values in the OnBarUpdate method.
Yes, I know about adding additional data series to an indicator.
But, My scenario's a bit more complex than that.
Yes, By uncommenting the "fix" code shown in the example code above, I'm able to make the indicator work perfectly in historical-only situations because the thread is blocked in OnStateChange until the request is completed. Blocking a thread in OnStateChange appears not to affect bars requests, unlike OnBarUpdated.
But, My "real" code doesn't use ManualResetEvents for blocking. It uses other logic to determine whether the background data processing has progressed far enough to allow OnBarUpdate to run for the current bar, and uses spin/sleep cycles to block OnBarUpdate until the data is ready.
When the data feed is connected and new bars are forming, if any blocking is performed in OnBarUpdate, the bars request will get deadlocked and stop providing incoming data.
Do you have any suggestions about how I can make my indicator compatible with 3rd-party indicators that expect data to be available in the OnBarUpdate method, whilst not deadlocking the bars requests?
Comment