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

NTWindow thread ownership

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

    NTWindow thread ownership

    Hello fellow humans,
    I'm experiencing a weird error. I've developed a custom AddOn window as a PopUp Dialog. I'm calling it from within an indicator and sometimes this indicator throws the error that some other thread owns this object already. I cannot replicate it reliably, but I can narrow it down to the general use of that custom NTWindow and the witch between different charts or tabs. As far as I've observed it, it doesn't matter whether a PopUp window ist shown or not, i.e. if it was once shown then closed this error still could occur. DO I have to handle switches between tabs or something similar?

    This is how the window gets called:
    Code:
    Globals.RandomDispatcher.InvokeAsync(new Action(() =>
                    {
                        if (PopUp != null)
                            PopUp.Close();
                        
                        PopUp = new PopUpWindow()
                        {
                            Caption = "SuperTrenderMA Pullback Alert",
                            message = message,
                            TextColor = ChartControl != null ? ChartControl.Properties.ChartText : Brushes.Black
                        };
                        
                        PopUp.Show(); // open the window
                        PopUp.Activate(); // bring to the top
                    }));​
    And this is the window itself:
    Code:
    namespace NinjaTrader.NinjaScript.AddOns
    {
        public class PopUpWindow : NTWindow
        {
            private Button        okButton;
            private TextBlock    messageBlock;
            
            public string     message;
            public Brush    TextColor;
            
            public PopUpWindow()
            {
                Caption        = "PopUp v1.0.1";
                Width        = 200;
                Height        = 120;
                TextColor    = Brushes.Black;
    
                Loaded        += OnWindow_Loaded;
                Closing        += OnWindow_Close;
            }
    
            private void OnWindow_Loaded(object sender, RoutedEventArgs e)
            {
                Content = LoadXaml();
            }
    
            private void OnWindow_Close(object sender, System.ComponentModel.CancelEventArgs e)
            {
                if (okButton != null)
                    okButton.Click -= OnOkButton_Click;
            }
    
            private DependencyObject LoadXaml()
            {
                Page page = new Page();
                
                FileStream fs = new FileStream(System.IO.Path.Combine(NinjaTrader.Core.Globals.UserDataDir, @"bin\Custom\AddOns\PopUpWindowContent.xaml"), FileMode.Open);
    
                page = (Page)XamlReader.Load(fs);
    
                if (page == null)
                    return null;
                
                messageBlock = LogicalTreeHelper.FindLogicalNode(page, "MessageBlock") as TextBlock;
                if (messageBlock != null)
                {
                    messageBlock.Text = message;
                    messageBlock.Foreground = TextColor;
                }
    
                okButton = LogicalTreeHelper.FindLogicalNode(page, "OkButton") as Button;
                if (okButton != null)
                    okButton.Click += OnOkButton_Click;
    
                DependencyObject pageContent = page.Content as DependencyObject;
    
                return pageContent;
            }
    
            private void OnOkButton_Click(object sender, RoutedEventArgs e)
            {
                this.Close();
            }
        }
    }​

    #2
    Hello Human#102,

    In the first code you posted you are using a variable called PopUp which if that is already assigned will be on a different thread than the new random thread you are working in. You would need to use the original thread from the PopUp variables dispatcher to interact with the previous popup before you re assign that variable.
    JesseNinjaTrader Customer Service

    Comment


      #3
      Hi Jesse,
      Thank you for the reply. I've tried to use the Dispatcher of the indicator, and that solves that issue. However, it only seems to "update" when the respective chart or window is active. How can I trigger or show that PopUp, even if I have another chart open primarily? Or do I have to somehow select the chart where I have added the indicator and set it as the active one first?

      Comment


        #4
        Hello Human#102,

        The dispatcher for the indicator is not the dispatcher for the window, you should only use the dispatcher from the window itself to avoid threading problems.

        Code:
        if (PopUp != null)
        {
        PopUp.Dispatcher.InvokeAsync(new Action(() =>
        {
             PopUp.Close();​
        });
        }
        
        Globals.RandomDispatcher.InvokeAsync(new Action(() =>
        {
        PopUp = new PopUpWindow()
        {
        Caption = "SuperTrenderMA Pullback Alert",
        message = message,
        TextColor = ChartControl != null ? ChartControl.Properties.ChartText : Brushes.Black
        };
        
        PopUp.Show(); // open the window
        PopUp.Activate(); // bring to the top
        }));​
        To have your indicator update in the background it needs IsSuspendedWhileInactive to be set to ​false. https://ninjatrader.com/support/help...leinactive.htm
        JesseNinjaTrader Customer Service

        Comment


          #5
          Hmmm, with this implementation it seems to queue up in the background if I'm on another tab/chart.

          Comment


            #6
            Hello Human#102,

            From the given details it is not clear what you are trying to do and how changing the tab is related. Are you trying to update something in the window when you change a tab?
            JesseNinjaTrader Customer Service

            Comment


              #7
              My goal is to create notifications in the form of PopUp windows. Ideally, even when I'm on other tabs, these PopUps should show up whenever a new notification takes place. Currently, the only working solution is to use the Indicator's dispatcher, but this only shows the PopUps when I select the tab to which chart this indicator is added, and not while I'm on other tabs.

              Comment


                #8
                Hello Human#102,

                When you switch tabs the indicator is backgrounded, did you set IsSuspendedWhileInactive to false and then remove and re apply the indicator? It also depends on what events you are trying to call the new window from.
                JesseNinjaTrader Customer Service

                Comment


                  #9
                  Sorry for the confusion Jesse, I was overlooking a region hiding a few settings including `IsSuspendedWhileInactive = true`. Now it works like a charm, thank you for the supports. ^^

                  Comment


                    #10
                    Hi again,
                    Unfortunately I found another issue which I cannot resolve.
                    When I run this indicator at one location, it works without any issues. If I add the indicator to multiple charts, or e.g. multiple Market Analyzers, these PopUps cause the error that they cannot access the xaml file due to another process already accessing it. The error itself makes sense, but it doesn't make sense why this error will occur in the first place. Is it not possible for multiple instances of an indicator to access the same add on xaml file? Or even further, for different indicators or strategies to access the same xaml file possible simultaneously? How can I manage this to still be possible?
                    Last edited by Human#102; 02-09-2024, 05:05 AM.

                    Comment


                      #11
                      Hello Human#102,

                      How frequently are you opening a new window and closing the last window? Your script should only be accessing the xaml file once when the window is initially created, after that it won't need to reload again unless you close the window so access shouldn't be a problem. If you are closing and re opening the window to update the values in the window that may be the problem, you shouldn't need to do that you can just update the existing window without having it reload the xaml.
                      JesseNinjaTrader Customer Service

                      Comment


                        #12
                        The entire creation and handling of the windows is pretty much as I've shown in the initial post, including your fix as well. Perhaps it helps to know that: the first instance of this indicator which is added somewhere, does not have this error, it functions properly. But every subsequent instance faces this error, as if the first instance blocks the file access. The variable `PopUp` is also not accessed for anything outside the shown code.

                        Comment


                          #13
                          Hello Human#102,

                          I would suggest posting a small test script that demonstrates the problem so we can better understand what may be happening. Just as an example the addon sample from the help guide does not have this problem and can have many instances open at once however each instance is only loading the xaml one time when its first created which would not be at the same time as another script.

                          JesseNinjaTrader Customer Service

                          Comment


                            #14
                            Hi Jesse,

                            I've done some more testing and found that it is highly inconsistent. In general it happens more often when I use it on high replay speeds, but I suspect it is in general caused when one thread/process tries to open a new popup while another process is not "finished" opening it, thus still accessing the xaml file. I've attached some example code, though for some reason in the market analyzer it only works added to one Market Analyzer window and not multiple. I've also included a template for the market analyzer (it loads only one bar of data, due to the bug that State is not being set to historical in the market analyzer).
                            So, I think maybe it would be smarter to look at this error from another perspective: If, for whatever reason, it happens that multiple processes are trying to open a PopUp at the exact same time, i.e. accessing the xaml at the exact same time, how can I allow it to happen without running into this error? Is there a way to perhaps detect that the file is being used by another process and then e.g. wait for a moment?
                            Attached Files

                            Comment


                              #15
                              Hello Human#102,

                              In the sample that you provided you are continuously opening and closing a window with OnBarUpdate, that would not be an expected way to use a window which is why you are having a problem. A window should only be opened one time and if some other data needs to be shown at a later time you would use the existing window instance and update values in the window.
                              JesseNinjaTrader Customer Service

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by Haiasi, 04-25-2024, 06:53 PM
                              2 responses
                              17 views
                              0 likes
                              Last Post Massinisa  
                              Started by Creamers, Today, 05:32 AM
                              0 responses
                              5 views
                              0 likes
                              Last Post Creamers  
                              Started by Segwin, 05-07-2018, 02:15 PM
                              12 responses
                              1,786 views
                              0 likes
                              Last Post Leafcutter  
                              Started by poplagelu, Today, 05:00 AM
                              0 responses
                              3 views
                              0 likes
                              Last Post poplagelu  
                              Started by fx.practic, 10-15-2013, 12:53 AM
                              5 responses
                              5,407 views
                              0 likes
                              Last Post Bidder
                              by Bidder
                               
                              Working...
                              X