This is a migrated thread and some comments may be shown as answers.

Adding event to Context Menu causes memory leak

5 Answers 363 Views
RichTextBox
This is a migrated thread and some comments may be shown as answers.
danparker276
Top achievements
Rank 2
danparker276 asked on 21 Jun 2011, 10:39 PM
I have an OOB app that will call a RadChildWindow that contains a RichTextBox.  I get a memory leak when I repopulate the content of the window, or if I close it and reopen it again.  This only happens when add a showing or closing event to the context menu.  I moved it to a empty control like below and it still caused memory leaks.  pressing a button to populate the child window 50 times will make the memory balloon to 500k or so.  Also, if I minimize the application, the memory seems to clear.  Just populate a radchildwindow with the code below and you should see the problem.
public BlankControl()
{
    InitializeComponent();
    Telerik.Windows.Controls.RichTextBoxUI.ContextMenu contextMenu = (Telerik.Windows.Controls.RichTextBoxUI.ContextMenu)this.rrtbDescription.ContextMenu;
    contextMenu.ContentBuilder = new CustomMenuBuilder(this.rrtbDescription);
    contextMenu.Showing += new EventHandler<ContextMenuEventArgs>(contextMenu_Showing);
    contextMenu.Closed += new EventHandler(contextMenu_Closed);
}
void contextMenu_Closed(object sender, EventArgs e)
{
}
void contextMenu_Showing(object sender, ContextMenuEventArgs e)
{
}
<Grid x:Name="LayoutRoot" Margin="2">
    <telerik:RadRichTextBox Name="rrtbDescription" Grid.Row="4" Width="600" Height="200" Margin="0,10,0,0"
                    DataContext="{Binding}"     IsSpellCheckingEnabled="True"
                    BorderThickness="1" BorderBrush="Black" IsSelectionMiniToolBarEnabled="False"
                    IsContextMenuEnabled="True" 
                    AcceptsTab="False" AcceptsReturn="False"
                    >
 
        <telerik:RadRichTextBox.Effect>
            <DropShadowEffect Color="Gray"
                    Opacity=".50"
                    ShadowDepth="8" />
        </telerik:RadRichTextBox.Effect>
 
    </telerik:RadRichTextBox>
</Grid>

5 Answers, 1 is accepted

Sort by
0
danparker276
Top achievements
Rank 2
answered on 22 Jun 2011, 02:36 AM
Oh, I'm also using the custom menu builder.  Adding this doesn't cause the memory leak, but I should probably add it to the post.

public class CustomMenuBuilder : ContextMenuContentBuilder
{
    private RadRichTextBox rrtb = new RadRichTextBox();
 
    public CustomMenuBuilder(RadRichTextBox rrtb)
        : base(rrtb)
    {
        this.rrtb = rrtb;
 
    }
    protected override ContextMenuGroup CreateTextEditCommands()
    {
        return new ContextMenuGroup();
    }
 
}
0
Alex
Telerik team
answered on 23 Jun 2011, 07:48 AM
Hello danparker276,

There is indeed memory leak caused by the attached event handlers. Let me clarify things a bit. Whenever new RadRichTextBox is created an instance of ContextMenu is assigned for it. This is instance is created by MEF at run time and is shared between all rich text boxes instances. Also the instance of the ContextMenu is cached by MEF and it is never garbage collected in order to be ready to use whenever new rich text boxes are created.

So what happens in your scenario is that every time you add an event handler to the Closed event inside the BlankControl class, you are adding this event handler to the same context menu that is cached by MEF and is never collected. This is prevents current instance of the BlankControl itself  to be garbage collected because the assigned event handler connects it to cached the context menu.
That said, you have two options to avoid the leak:
  1. Modify you application so that the events you attach to the context menu are detached when the control that uses them is no longer needed.
  2. When you create RadRichTextBox assigne to it a new instance of a Telerik.Windows.Controls.RichTextBoxUI.ContextMenu class. This is the way, the event handlers you attach to it will not hold a reference to the context menu created by MEF (which is not collected) and will not prevent you control from being garbage collected.

I hope this helpful. Do not hesitate to send us a support ticket if you need more specific help.

Best wishes,
Alex
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
danparker276
Top achievements
Rank 2
answered on 23 Jun 2011, 06:13 PM
How can I detach the events when the Child window is closed?

for #1:
how could I remove the events from the closed events?:
        void myRadWindow_Closed(object sender, WindowClosedEventArgs e)
        {

and for #2:
I'm creating it in the xaml, how would I assign a new instance of the Telerik.Windows.Controls.RichTextBoxUI.ContextMenu class?
Are you saying do this:
                    Telerik.Windows.Controls.RichTextBoxUI.ContextMenu contextMenu = new Telerik.Windows.Controls.RichTextBoxUI.ContextMenu();
                    rrtbDescription.ContextMenu = contextMenu;

This didn't work.


I basically just want to check if the context menu has focus.  That's all I'm using it for.  Is there another way to check, other that creating events for it.
0
danparker276
Top achievements
Rank 2
answered on 23 Jun 2011, 08:29 PM
I've tried the following, but it didn't work
            var aaa = myRadWindow.ChildrenOfType<RadRichTextBox>();
            foreach (RadRichTextBox a in aaa)
            {
 
                Telerik.Windows.Controls.RichTextBoxUI.ContextMenu contextMenu = (Telerik.Windows.Controls.RichTextBoxUI.ContextMenu)a.ContextMenu;
                contextMenu.Showing -= null;
                contextMenu.Closed -= null;
                contextMenu = null;
...
or just
                a.ContextMenu = null;
 
            }
also tried
WindowData wd= (WindowData ) this.myRadWindow.DataContext;
 
          var aaa = this.myRadWindow.ChildrenOfType<RadRichTextBox>();
          foreach (RadRichTextBox a in aaa)
          {
              Telerik.Windows.Controls.RichTextBoxUI.ContextMenu contextMenu = (Telerik.Windows.Controls.RichTextBoxUI.ContextMenu)a.ContextMenu;
              contextMenu.Showing -= new RoutedEventHandler(wd.contextMenu_Showing);
 
it didn't like that though
0
Accepted
Alex
Telerik team
answered on 29 Jun 2011, 12:10 PM
Hi danparker276,

I've attached a sample project which shows one way of how the detaching of the events can be done. Basically, the detaching is done in the DetachFromEvents() method of the BlankControl and this method is called whenever the RadWindow is closed.

I hope this is helpful. If you need further assistance please don't hesitate to open support ticket and send as a sample project so we can provide a more specific solution.

All the best,
Alex
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Tags
RichTextBox
Asked by
danparker276
Top achievements
Rank 2
Answers by
danparker276
Top achievements
Rank 2
Alex
Telerik team
Share this question
or