Notifications
Clear all

[Closed] More garbage collection and event handlers

Hello,

the topic has been addressed before but i’ve managed to create a similar but slightly different problem which i’m unable to solve.
I’ve got a form with controls. It’s all dotNet. When creating menuStrips or contextMenuStrips I add single menuStripItems to menustrips. I’ve secured my menustripItems in an array which is stored in a struct. This prevents the menuItems from loosing their eventhandlers when garbage collection occurs. That’s working fine.

Recently i’ve been creating dotNet itemCollections which contain my menuItems. The advantage is i can call the separate items by their names instead of using indices. It helps me understand my own code better. I also secure these collections (a single dotNet object) in a variable in a struct. This doesn’t prevent the garbage collection from wiping the event handlers from these menuItems though.

The example shows two collections of menuItems. The first collection survives garbage collection, the second one doesn’t. Can anyone help me with this?

Klaas

struct myDotNetFormStruct
  (
  	-- ========== Properties ==========
  	frmNewAsset,
  	theMenu,
  	btnTest,
  	
  	mainMenuStripItemArray,
  	subMenuStripItemArray, --this will be an array which contains separate "toolStripMenuItems"
  	subMenuStripItemCollection, --this will be a "toolstripMenuItemCollection"
  	
  	-- ========== UI Handlers ==========
  	 fn fn_diagnoseButton control arg =
  	 (
  		format "This control works. It's name is: %
" control.text
  	 ),
  	 
  	 fn fn_garbageCollect control arg =
  	 (
  		gc()
  		print "Taken out the trash"
  	),
  	
  	-- ========== Methods ==========
  	--this method fills an ordinary array with toolstripMenuItems
  	function fn_createMenuItems itemStringArray =
  	(
  		local theItemArray = #()
  		for str in itemStringArray do
  		(
  			local item = dotNetObject "System.Windows.Forms.ToolStripMenuItem"
  			item.name = str
  			item.text = str
  			append theItemArray item
  		)
  		theItemArray --return an array of toolStripMenuItems
  	),
  
  	--this method creates a dotNet toolstripItemCollection
  	function fn_createToolstripMenuItems itemStringArray =
  	(
  		local tempToolstrip = dotNetObject "System.Windows.Forms.ContextMenuStrip"
  		for str in itemStringArray do
  		(
  			local item = dotNetObject "System.Windows.Forms.ToolStripMenuItem"
  			item.name = str
  			item.text = str
  			tempToolstrip.items.add item
  		)
  		tempToolstrip.items
  	),
  
  	-- ========== Constructor ==========
  	fn constructor =
  	(				
  		-- Form init
  		frmNewAsset = dotNetObject "Form"
  		frmNewAsset.Size = dotNetObject "System.Drawing.Size" 300 200		
  		frmNewAsset.text = "garbage collect and weep"
  		-- Menus
  		theMenu = dotNetObject "menustrip"
  		--defining the menuitems
  		 mainMenuStripItemArray = fn_createMenuItems #("these work","these don't")
  		 subMenuStripItemArray = fn_createMenuItems #("these items are stored","as separate toolstripMenuItems","in a max-array and are","protected from garbage collection")
  		 subMenuStripItemCollection = fn_createToolstripMenuItems #("these items are stored","as a single toolstripMenuItemCollection","and loose their event handler when","garbage collection occurs","why?")
  		-- Button
  		btnTest = dotNetObject "button"
  		btnTest.location = dotNetobject "System.drawing.point" 30 80
  		btnTest.size = dotNetobject "System.drawing.size" 150 30
  		btnTest.text = "garbage collect"	
  		dotNet.addEventHandler btnTest "click" fn_garbageCollect
  		--adding the menuItems to the menu and also add their event handlers
  		theMenu.items.addRange mainMenuStripItemArray
  		theMenu.items.item["these work"].dropDownItems.addRange subMenuStripItemArray
  		for i in subMenuStripItemArray do dotNet.addEventHandler i "click" fn_diagnoseButton
  		for i = 0 to 4 do
  		(
  			dotNet.addEventHandler subMenuStripItemCollection.item[0] "click" fn_diagnoseButton
  			theMenu.items.item["these don't"].dropDownItems.add subMenuStripItemCollection.item[0]
  		)
  		-- Form init
  		controlArray = #(theMenu,btnTest) --an array with controls to be added to the form
  		frmNewAsset.controls.addRange controlArray
  		frmNewAsset.show() --show a form 
  	),
  	tmp = constructor()	
  )
  myDotNetForm = myDotNetFormStruct() 

similar issues:
http://area.autodesk.com/index.php/forums/viewthread/12429/
http://forums.cgsociety.org/showthread.php?f=98&t=622470&highlight=garbage+dotnet