As an example, consider the code:
namespace NinjaTrader.NinjaScript.Indicators
{
public class TestPrematureTermination : Indicator
{
private bool IsUpdating = false;
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = @"Test premature termination issue, NT 8 beta 9";
Name = "TestPrematureTermination";
}
else if (State == State.Terminated)
{
if (IsUpdating) throw new Exception("Premature termination");
}
}
protected override void OnBarUpdate()
{
IsUpdating = true;
System.Threading.Thread.Sleep(1);
IsUpdating = false;
}
}
}
This demonstration is very basic, and obviously could be done differently. But unless it is by deliberate design that an indicator can be terminated while an individual bar or tick is still in OnBarUpdate, this seems like an oversight and likely to cause many complications. A reasonable expectation on the part of an indicator designer might be that the indicator may be terminated at any time between ticks or bars, but not concurrent with the calculation of any one tick or bar. What actually happens is that randomly, OnStateChange changes to Terminated the state while OnBarUpdate is still calculating a tick or bar. This can be easily demonstrated by putting this indicator on a chart and hitting F5 a few times until it happens (example screenshot attached).
I can easily imagine how this happened, but it would be quite reasonable to assume that despite the multithreading approach the indicator will not be destroyed while it is still calculating - if that is by design, it would require extraordinary handling on the part of indicator developers to deal with it, especially if they use any unmanaged resources.
The consequence of it working the way that it currently does is that indicator designers cannot rely on the Terminated state change to safely dispose of resources the indicator uses, because OnBarUpdate might still be running and using them.
While it is possible to work around this in NinjaScript code, it seems like it is most likely an oversight and the sort of thing that will cause many people many issues in the future because the resources will be disposed while they are still being accessed.
A simple solution NT's developers could use is to wait until OnBarUpdate exits before changing the state to terminated. If that were done, the common sense assumption could once again be that the state change to Terminated is where resources can be safely cleaned up.
This does not happen only when there is a Sleep() involved - however, by adding the Sleep() it is easier to demonstrate quickly. This issue originally surfaced here on indicator code that only does calculations.
Comment