We have an issue where our application keeps on eating up RAM so I slapped some Diagnostic Tools on it and viewed three different snapshots of the process memory and noticed that each time we search for a user, the object (a form) created, is not being disposed on the forms Close().
This is the code which happens when a user is searched.
private void btnSearch_Click(object sender, EventArgs e)
{
frmCombinedSearch frmCmbSearch = new frmCombinedSearch();
try
{
// Shows the 'form' in the same tab. This is a tabbed control.
frmCmbSearch.ShowInTab(this.ParentTabPage);
}
catch (Exception ex)
{
this.ShowException(ex);
}
}
Once frmCombinedSearch is shown, the object lives on until another button is hit which eventually fires the this.Close() event on the form. From my understanding, the object is marked to be free'd up by the GC after this point.
After looking into the objects being created in the Diagnostic Tools session, I noticed that the object has Event Handlers that aren't unsubscribed from.
Below is the snippet from the Diagnostic tools which shows the additional objects being created after four person searches.
How can I unsubscribe from the events manually so that the GC can free up the resources?
Related
So I have a simple class:
public class GridButton : Button
{
public event EventHandler OnClick;
public GridButton()
{
this.Clicked += GridButton_Clicked;
}
private void GridButton_Clicked(object sender, EventArgs e)
{
HandleTap();
}
Now as this is a view control I am not in charge of when this object is disposed.
Is the above code a memory leak or is the GarbageCollector clever enough to work out that the event handler is self referencing and so doesn't cause a leak.
If this is a memory leak what is the correct solution?
Should I be using a more WeakRefence like the one oulined here?
http://paulstovell.com/blog/weakevents
The .NET garbage collector will find and delete cycles (this -> OnClick -> this.GridButton_Clicked).
"Memory leaks" in .NET tend to occur when you have say a collection (be that a list, map, events, whatever) that will never be freed (e.g. a global/static variable, or up at the start of the stack which won't go out of scope during the program), and then you keep adding more items to that over time, but never remove them.
For example:
public GridButton()
{
Globals.OnRefreshClicked += Refresh;
}
private void Refresh()
{
...update text, state, whatever...
}
Where "Globals" is anything long-lived. Now even if you remove this button from the GUI, unless you also remove that event, the Globals.OnRefreshClicked -> this.Refresh reference will keep your object alive, at least as long as Globals, which could be until the program terminates.
I was wondering if there is a more efficient way of opening a fresh window in WPF than how presented in code below :
WindowConfigureDatabase windowConfigureDatabse;
private void ButtonConfigureDatabase_Click(object sender, RibbonControlEventArgs e)
{
if (windowConfigureDatabase == null)
{
windowConfigureDatabase = new WindowConfigureDatabase();
}
windowConfigureDatabase.Clear();
windowConfigureDatabase.Show();
windowConfigureDatabase.WindowState = WindowState.Normal;
}
Where windowConfigureDatabase is the new window I want to open. windowConfigureDatabase.Clear(); just resets all the values to default - there aren't many of them to reset. I was wondering whether or not this is the proper way of opening new windows in wpf. The other path I was thinking of was just simply creating a new window on each button click (that way I don't have to clear values each time...) but I'm afraid of allocating too much memory if a user opens the window and closes it a lot of times as I'm not quite sure if garbage collector picks the window up on OnClose event.
So basically my question is - does the garbage collector pick my windows up after I close them during Closing/Closed event? If not, what would be the proper way of managing the window's memory manually? Would adding a
windowConfigureDatabase = null
on Closed/OnClosing event do well?
does the garbage collector pick my windows up after I close them
during Closing/Closed event?
Yes, if unreachable. Read up on this for a better idea.
Would adding a
windowConfigureDatabase = null
on Closed/OnClosing event do well?
Yes. Failing to do this will prevent the window from being garbage collected until windowConfigureDatabase is overwritten or the object containing it is collected.
The memory used by a window depends on its dimensions and how much memory it allocates to do what it needs to do. You generally don't need to worry about this unless you're creating tons of windows(~30+) and/or large volumes of data.
The fastest way to allocate is to allocate up front(ideally at startup) and reuse when possible. Fortunately with windows this is relatively easy. The idea is to hide instead of close, and only close when truly no longer needed.
Like this:
// In each window class or as a base class:
private bool isClosable = false;
protected override void OnClosing(CancelEventArgs args)
{
// Prevent closing until allowed.
if (!isClosable) {
args.Cancel = true;
Hide();
}
base.OnClosing(args);
}
// Call this when you want to destroy the window like normal.
public void ForceClose()
{
isClosable = true;
Close();
}
I have a hardware ware device that needs to be unloaded at the end of program execution or it will be left in an undefined/unstable/dangerous state. This is easy enough during normal operation, but during any sort of crash or unexpected circumstance, it usually doesn't get unloaded properly.
Searching, I found that I can setup an event to clean up the board on process exit, or at least a fraction of them:
public MainForm()
{
...
AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);
...
}
static void OnProcessExit(object sender, EventArgs e)
{ myHardwareDevice.checkAndPerformSafeShutdown();
}
where checkAndPerformSafeShutdown is a wrapper around native dll function call that cleans up the driver and puts all hardware in a safe state. However, this fails to compile with:
error CS0120: An object reference is required for the non-static field, method, or property 'projectNme.MainForm.myHardwareDevice'.
What is the scope of this event handler and why is it different then any other event handler in the class? Is there someway I can get a reference to the hardware device?
Define the event handler as an instance method on your MainForm and you'll have access to all instance variables.
I'm having an issue with regards on memory management with our system.
Basically here is my design:
Load the List of the Records.
frmBrowse Memory used
90MB
After clicking record, it will pop another form which is the detailed form of the record selected
frmAP
Memory used 110MB
private void ViewRecord()
{
try
{
if(oAP!=null)
oAP = new frmAP();
oAP.LoadRecordDetails();
oAP.Show();
}
catch (Exception ex)
{
clsClass.oGenMethods.ErrorMessage(ex.Message, "frmBrowse", "EditSearchFields");
}
}
When the user CLOSE, i actually Hide it (frmAP )to prevent re-query datas such as lookup tables and others - frmAP - Memory used 110MB
On the frmAP_Close()
this.Hide();
-Memory at 110MB
After hiding the form (frmSomeForm ) the memory remains at 110MB
When the user close the Form(frmBrowse) where "frmAP" was called/instantiate
public void tsClose_Click(object sender, EventArgs e)
{
if (oAP != null)
{
oAP .Dispose();
oAP .Close();
GC.Collect();
}
}
The Problem is the Memory is Still at ~110MB Whether the List(frmBrowse) Form and the Record form(frmAp) was closed.
Please advice
Thanks in Advance
UPDATE:
i Tried to delete .Hide() to isolate the problem, but still the memory keeps growing
Calling Close does not release the memory associated with an object. That's the job of the garbage collector. Close or Dispose simply tells the object to release any unmanaged memory or resources it is using. The object, and everything it's referencing, still stays in memory.
To ensure oAP is collected, set it to null:
oAP.Close();
oAP = null;
However, this is likely the wrong thing to do. The whole point of a garbage collector is to collect memory from unreferenced objects when it's needed. So let it do its job, don't force it to run, you don't need to set oAP to null, and oAP and everything it references will be collected when the GC needs to.
I need certain criteria to be met, a particular folder needs to be present on the c drive, before this app should load. How, during the load process, can I stop/quit the application.
I already have ascertained if the folder exists. In old VB projects you would just use 'Unload Me' but that isn't in C#. I tried Application.Exit() but that doesn't work under these circumstances and the app still loads, how do I stop it?
Open up Program.cs. In there you'll find you Main() method.
In there, put something like:
if (FolderDoesNotExist())
return ERROR_FOLDER_NOT_EXIST;
(replacing those symbolic names with other stuff as appropriate).
I would create an initialization function that would be the first item to be called from Main(). Depending on your output and how long your initialization takes you can even use a splash window to inform the user about progress. Once all initialization is completed, you can decide if you start the app or not.
// In the main initialization of the main form (in XXX.Designer.cs file InitializeComponent(), for example)
this.Load += new System.EventHandler(this.CheckProcesses);
// The CheckProcess method
private void CheckProcesses(object sender, EventArgs e)
{
try { if (SomethingIsWrongWithThatFolder()) this.Close(); }
catch { }
}
// This will shut the process of your app before the UI actually loads. So, your user doesn't see anything at all