Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

OnStateChange error when connectiing

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    OnStateChange error when connectiing

    Here is the problem definition :

    I open NinjaTrader
    I DO NOT connect and apply an indicator that I have developed. That indicator includes a toobar with multiple buttons on it.
    Everything fine.

    Connect to data.
    Duplicating tool bar and error message : Error on calling 'OnStateChange' method: The calling thread cannot access this object because a different thread owns it.


    If I connect before adding the indicator everything's fine and I have no error.

    In my code I use the Dispatcher.InvokeAsync to built the toolbar menu and I also use the dispatcher to dispose in OnTerminated method.

    Seems to reload the indicator on connection without disposing of previous indicator.

    Need guidance

    Thank you

    #2
    Hello blar58, and thank you for your report.

    It sounds like we need to ensure this is being dispatched just once. I would like to recommend using a boolean class flag to ensure this only runs once, e.g.

    Code:
    [FONT=Courier New]private bool hasDispatched;
    protected override void OnStateChange()
    {
        if (State == State.Configure)
        {
            if (! hasDispatched)
            {
                Dispatcher.InvokeAsync(new YourAction());
                hasDispatched = true;
            }
        }
    }[/FONT]
    You will also want to review this section of the help guide.



    On that page is a very helpful tool which will help you avoid exactly this situation. This will let you see whether the dispatched action has already been sent off.

    Code:
    [FONT=Courier New]// check if the current object is already on the calling thread
    if (Dispatcher.CheckAccess())
    {
      // execute action directly
      action(args);
    }
    // otherwise run the action from the thread that created the object
    else
    {
      // dispatch action to calling thread
      Dispatcher.InvokeAsync(action, args);
    }[/FONT]
    Please let us know if there are any other ways we can help.
    Jessica P.NinjaTrader Customer Service

    Comment


      #3
      Thank you Jessica.

      I was already using Dispatcher.CheckAccess and was using the pattern shown on your documents.

      I have found the problem and it was related to the fact that my menu was added to NinjaTrader Trader instead of UserCollection.

      Comment


        #4
        I have the same problem.

        I've created custom menu items which add themselves to the chart context menu as part of an indicator.

        However, when I connect to a datafeed, I get the error above as well as duplication of the menu items in my context menu.

        I am using the Dispatcher and CheckAccess patterns as above.

        any ideas?

        thanks

        Comment


          #5
          Thank you for your question trader_rick. Would you be able to provide a small code sample which demonstrates this that we can use to see the same thing on our end?
          Jessica P.NinjaTrader Customer Service

          Comment


            #6
            Here you go.

            thanks

            Code:
            namespace NinjaTrader.NinjaScript.Indicators
            {
                public class aaHistoricalTrader : Indicator
                {
                    private MenuItem mciBuy;
                    private MenuItem mciSell;
            
                    private Point clickPoint = new Point();
                    private ChartScale cs;
            
                    private string orderArguments;
                    private bool hasDispatched = false;
                    private double executionPrice;
                    private System.DateTime executionTime;
            
                    protected override void OnStateChange()
                    {
                        if (State == State.SetDefaults)
                        {
                            Description                                = @"Creates context menu to allow you to enter trades on historical data.";
                            Name                                        = "aaHistoricalTrader";
                            Calculate                                = Calculate.OnBarClose;
                            IsOverlay                                = true;
                            DisplayInDataBox                        = false;
                            DrawOnPricePanel                        = true;
                            DrawHorizontalGridLines                = true;
                            DrawVerticalGridLines                = true;
                            PaintPriceMarkers                        = true;
                            ScaleJustification                    = NinjaTrader.Gui.Chart.ScaleJustification.Right;
                            IsSuspendedWhileInactive            = true;
                        }
                        else if (State == State.Configure)
                        {
                            mciBuy = new MenuItem();
                            mciSell = new MenuItem();
                            mciBuy.Click += mciBuy_Click;
                            mciSell.Click += mciSell_Click;
                        }
                        else if( State == State.Historical )
                        {
                            if( ChartControl != null )
                                ChartControl.MouseRightButtonDown += RClick;
                        }
                        else if (State == State.Terminated)
                        {
                            if( mciBuy != null )
                            {
                                if (ChartControl != null)
                                {
                                    ChartControl.ContextMenu.Items.Remove(mciBuy);
                                    mciBuy = null;
                                }
                            }
                            if( mciSell != null )
                            {
                                if (ChartControl != null)
                                {
                                    ChartControl.ContextMenu.Items.Remove(mciSell);
                                    mciSell = null;
                                }
                            }
                            if( ChartControl != null )
                                ChartControl.MouseRightButtonDown -= RClick;
                        }
                    }
            
                    protected override void OnBarUpdate()
                    {
                        if (ChartControl != null)
                        {
                            if( Dispatcher.CheckAccess() )
                            {
                                ChartControl.ContextMenu.Items.Add(mciBuy);
                                ChartControl.ContextMenu.Items.Add(mciSell);
                            }
                            else
                                {
                                ChartControl.Dispatcher.InvokeAsync(new Action(() =>
                                {
                                    if( !hasDispatched )
                                    {
                                        ChartControl.ContextMenu.Items.Add(mciBuy);
                                        ChartControl.ContextMenu.Items.Add(mciSell);
                                    }
                                    hasDispatched = true;
                                }));
                            }
                        }
                    }
            
                    protected void RClick( object sender, MouseButtonEventArgs e )
                    {
                        clickPoint.X = ChartingExtensions.ConvertToHorizontalPixels(
                                e.GetPosition(ChartPanel as IInputElement).X,
                                ChartControl.PresentationSource
                                );
                        clickPoint.Y = ChartingExtensions.ConvertToVerticalPixels(
                                e.GetPosition(ChartPanel as IInputElement).Y,
                                ChartControl.PresentationSource
                                );
            
                        executionTime = ChartControl.GetTimeByX( (int) clickPoint.X );
                        cs = ChartPanel.Scales[ ChartPanel.PanelIndex ];
                        if( cs != null )
                        {
                            executionPrice =
                                Instrument.MasterInstrument.RoundToTickSize( cs.GetValueByY( (float) clickPoint.Y ) );
                            //Set menu item and format to 2 fixed places.
                            mciBuy.Header = "Buy " + executionPrice.ToString( "f2" );
                            mciSell.Header = "Sell " + executionPrice.ToString( "f2" );
                        }
                    }
                }
            }

            Comment


              #7
              It looks like I am still not able to quite see the same thing that you are in a pre-release version of Ninja. Please attempt to use the attached C# file on your system. If you do not see the same thing, please compare the attached script to your own. If you do see the same thing, it is likely the case that this has been repaired, and I would invite you to attempt in the next release of Ninja. We're happy to help in any way we can.
              Attached Files
              Jessica P.NinjaTrader Customer Service

              Comment


                #8
                Thanks for the reply Jessica.

                Even though there are no material differences in your version (you just put in stub definitions to handle the clicks - my version has full definitions), once I loaded your version, both versions now work fine without errors and without me making any changes.

                One of those (exasperating) things.

                Thanks for the help.

                Comment


                  #9
                  Hi guys,

                  This error is back. I have 8.0.7 installed.
                  Connecting to a data feed provider when a chart has the above indicator loaded results in duplication of the custom menu items in the context menu. The items themselves are dead however - no callback is triggered on clicking them. (The original items work however.)

                  Disconnecting does not remove the items but reconnecting will cause yet another duplication. This can get quite irritating if I end up reconnecting several times (I normally leave my computer running 24/7).

                  Many thanks for any help you can offer.

                  Comment


                    #10
                    Hello Rick,

                    I am just letting you know we have received your post and are reviewing this case. We will return when we have more information.
                    Jessica P.NinjaTrader Customer Service

                    Comment


                      #11
                      There are some threading changes to NinjaTrader which caused this code to behave differently that we are investigating further.Please keep an eye on the NinjaTrader 8 Release Notes page for updates and bugfixes.





                      Tracking ID: NTEIGHT-11837
                      Jessica P.NinjaTrader Customer Service

                      Comment


                        #12
                        OK, thanks.

                        Comment


                          #13
                          I have some more information regarding this.

                          From now on, in every new version of NinjaTrader, all User Interface action such as updating menu buttons will need to take place in the main UI thread. There is an example of dispatching to this thread in the attached script between lines 105 and 112. Any action on ChartControl.ContextMenu.Items will need to be similarly dispatched. I recommend writing a simple CRUD layer into this item so that you can guarantee threading is properly maintained easily. This publicly available link has more information as to what is meant by CRUD.

                          Attached Files
                          Jessica P.NinjaTrader Customer Service

                          Comment


                            #14
                            I'm confused Jessica.

                            I already have exactly the same code in my indicator as in the example you provided. Unless you are saying that the problem will be resolved in future versions of NT and that you are pointing out the practice to be used with these future versions, which is what I believe I'm already currently doing.

                            Comment


                              #15
                              I am happy to clarify. The code sample I provided worked in a previous version of Ninja but will no longer work in current versions. This is due to changes in Ninja that have been done for consistency and predictability.

                              Attached is a code sample that should do something like what you are describing. Code samples we provide are for educational purposes, and are not intended for live trading, and are not guaranteed to accomplish any user goal or to be maintained.
                              Attached Files
                              Last edited by NinjaTrader_JessicaP; 06-22-2017, 09:07 AM.
                              Jessica P.NinjaTrader Customer Service

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by sidlercom80, 10-28-2023, 08:49 AM
                              167 responses
                              2,260 views
                              0 likes
                              Last Post jeronymite  
                              Started by warreng86, 11-10-2020, 02:04 PM
                              7 responses
                              1,361 views
                              0 likes
                              Last Post NinjaTrader_Manfred  
                              Started by Perr0Grande, Today, 08:16 PM
                              0 responses
                              5 views
                              0 likes
                              Last Post Perr0Grande  
                              Started by elderan, Today, 08:03 PM
                              0 responses
                              9 views
                              0 likes
                              Last Post elderan
                              by elderan
                               
                              Started by algospoke, Today, 06:40 PM
                              0 responses
                              10 views
                              0 likes
                              Last Post algospoke  
                              Working...
                              X