Memory not freeing after Obj.Close() - c#

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.

Related

Remove event references from Object for Garbage Collection to work

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?

A proper way of opening new wpf windows

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();
}

How do I properly dispose and free the memory used for V8.Net.V8Engine instances?

I'm running into an issue when using my V8Engine instance, it appears to have a small memory leak, and disposing of it, as well as forcing the garbage collection doesn't seem to help much. It will eventually throw an AccessViolationException on V8Enging local_m_negine = new V8Engine() claiming a Fatal error in heap setup, Allocation failed - process out of memory and Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Monitoring the program's memory usage through Task manager whilst running confirms that it is leaking memory, around 1000 KB every couple of seconds I think. I suspect it is the variables being declared within the executed script not being collected, or something to do with the GlobalObject.SetProperty method. Calling V8Engine.ForceV8GarbageCollection(), V8Engine.Dispose() and even GC.WaitForPendingFinalizers() & GC.Collect() doesn't prevent this memory being leaked (Although it is worth noting that it seems to leak it slower with these commands in place, and I know I shouldn't use GC but it was there as a last resort to see if it would fix the issue.)
A tangential issue that could also provide a solution is the inability to clear the execution context for V8Engine. I am required to dispose and re-instantiate the engine for each script, which I believe is where the memory leak is happening, otherwise I run into issues where variables have already been declared, causing V8Engine.Execute() to throw an exception saying such.
I can definitely confirm that the memory leak is something to do with the V8Engine Implementation, as running the older version of this program that uses Microsoft.JScript has no such memory leak, and the memory used remains consistent.
The affected code is as follows;
//Create the V8Engine and dispose when done
using (V8Engine local_m_engine = new V8Engine())
{
//Set the Lookup instance as a global object so that the JS code in the V8.Net wrapper can access it
local_m_engine.GlobalObject.SetProperty("Lookup", m_lookup, null, true, ScriptMemberSecurity.ReadOnly);
//Execute the script
result = local_m_engine.Execute(script);
//Please just clear everything I can't cope.
local_m_engine.ForceV8GarbageCollection();
local_m_engine.GlobalObject.Dispose();
}
EDIT:
Not sure how useful this will be but I've been running some memory profiling tools on it and have learnt that after running an isolated version of the original code, My software ends up with a large amount of instances of IndexedObjectList's full of null values (see here: http://imgur.com/a/bll5K). It appears to have one instance of each class for each V8Engine instance that is made, but they aren't being disposed or freed. I cant help but feel like I'm missing a command or something here.
The code I'm using to test and recreate the memory leak that the above implementation causes is as follows:
using System;
using V8.Net;
namespace V8DotNetMemoryTest
{
class Program
{
static void Main(string[] args)
{
string script = #" var math1 = 5;
var math2 = 10;
result = 5 + 10;";
Handle result;
int i = 0;
V8Engine local_m_engine;
while (true)
{
//Create the V8Engine and dispose when done
local_m_engine = new V8Engine();
//Set the Lookup instance as a global object so that the JS code in the V8.Net wrapper can access it
//local_m_engine.GlobalObject.SetProperty("Lookup", m_lookup, null, true, ScriptMemberSecurity.ReadOnly);
//Execute the script
result = local_m_engine.Execute(script);
Console.WriteLine(i++);
result.ReleaseManagedObject();
result.Dispose();
local_m_engine.Dispose();
GC.WaitForPendingFinalizers();
GC.Collect();
local_m_engine = null;
}
}
}
}
Sorry, I had no idea this question existed. Make sure to use the v8.net tag.
Your problem is this line:
result = local_m_engine.Execute(script);
The result returned is never disposed. ;) You are responsible for returned handles. Those handles are struct values, not class objects.
You could also do using (result = local_m_engine.Execute(script)) { ... }
There is a new version released. I am finally resurrecting this project again as I will need it for the FlowScript VPL project - and it now supports .Net Standard as well for cross-platform support!

Unmanaged Leak in Calling Web service in C#

I need help with my code.
Ive been trying to use RedGate to monitor the memory usage of my application, after hours of testing It pointed out the unmanaged code of my application, and I could only think of my webservice calling as the only or somewhat unmanaged part of my code. Ive been debugging for hours and cant seem to find out where or what really happened. below is my code.
private void btnstart_Click(object sender, EventArgs e)
{
btnPressed = !btnPressed //boolean
if(btnPressed)
{
myTask = Task.Factory.StartNew(() =>
{
do {
_checkMatches(token.Token);
} while (token.IsCancellationRequested != true);
},token.Token);
}
else
{
token.Cancel();
try {
Task.WaitAny(myTask);
}
catch(Exception Error) {
//Put to logs
}
finally
{
if(myTask.isCancelled || myTask.IsCompleted || myTask.IsFaulted)
{
myTask.Dispose();
}
}
}
}
private void _checkMatches(CancellationToken token)
{
try
{
if(token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
EndpointAddressBuilder ServiceEndPoint = new EndpointAddressBuilder(//Read Endpoint From Notepad);
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; });//just bypassing validation for test purposes
// WebService is an ASMX web service
using (WebService.SoapClient client = new WebService.SoapClient())
{
WebService.checkResponse clientRes = client.checkClient();
if(clientRes.response == 1 || clientRes.response == 2) {
//Put to Logs
}
}
}
catch(Exception error){
//Put to logs
}
}
I cant seem to find any error in this code. Can Someone Help me with what is the problem why my unmanaged code is leaking? or could someone suggest what tools to be used or even suggest to find the leaking part of my code? Any Help would be great.
If you are using RedGate memory profiler it should tell you more than just pointing unmanaged resources. Because you are not directly creating any unamanged resources, most likely your memory leak is caused by a managed object or an event subsciption(or callback subscription).
Standard .net managed objects which have unmanaged resources (ie : WebService.SoapClient) have implemented the finalizer(destructor) in order to get rid of its unmanaged resources in any case if Dispose is not called. If you use a standard .net managed object which has unmanaged resources and don't call the dispose (this is bad), still it will release unamanged resources when it is going through the finalization. Generally this shouldn't cause unmanaged resource memory leak.
How to check if there is any memory leak:
Execute your memory consumption logic a few times. Go to the Instance list and see if there is any instances are growing. Select the 'Objects with Source' option in order to get rid of heaps of system object. You should see more instances that there should be if there is any memory leak.
If there is any growing instances, pick one and see the objects retention graph which will show you exactly which instance holds the reference.
And also, make sure that you have implemented IDisposable properly and dispose all disposable objects and unsubscribe from all event subscriptions.
Have a look at below walkthroughs
http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/walkthrough http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/

Why do bitmaps stay in memory unless I call GC.Collect?

I'm developing an application that connects to a GigEVision camera, and pulls images from it. I'm currently using the Pleora eBus SDK with C#.NET.
The code below is just a test application for the camera connection - it can stream images, but rapidly runs out of memory unless I call GC.Collect();
It's worth noting the images being streamed are large (4096x3072), so the crash happens fairly quickly.
I suspected at first that not calling Dispose() was the issue. However, I can call Dispose() on each image right before getting rid of the reference to it, and that did not fix the issue.
I've also tried explicitly releasing the buffers that come into the display thread callback, but that had no effect.
Can I get my memory back in a more elegant way?
using System;
using System.Windows.Forms;
using PvDotNet;
using PvGUIDotNet;
using System.Drawing;
namespace eBus_Connection
{
public partial class MainForm : Form
{
PvDeviceGEV camera;
PvStreamGEV stream;
PvPipeline pipeline;
PvDisplayThread thread;
bool updating = false;
public MainForm()
{
InitializeComponent();
}
private void MainForm_Shown(object sender, EventArgs e)
{
PvDeviceInfo info;
PvDeviceFinderForm form = new PvDeviceFinderForm();
form.ShowDialog();
info = form.Selected;
camera = PvDeviceGEV.CreateAndConnect(info) as PvDeviceGEV;
stream = PvStreamGEV.CreateAndOpen(info.ConnectionID) as PvStreamGEV;
pipeline = new PvPipeline(stream);
if (camera == null || stream == null)
throw new Exception("Camera or stream could not be created.");
camera.NegotiatePacketSize();
camera.SetStreamDestination(stream.LocalIPAddress, stream.LocalPort);
camera.StreamEnable();
camera.Parameters.ExecuteCommand("AcquisitionStart");
pipeline.Start();
thread = new PvDisplayThread();
thread.OnBufferDisplay += thread_OnBufferDisplay;
thread.Start(pipeline, camera.Parameters);
status.DisplayThread = thread;
status.Stream = stream;
}
void thread_OnBufferDisplay(PvDisplayThread aDisplayThread, PvBuffer aBuffer)
{
Bitmap b = new Bitmap((int)aBuffer.Image.Width, (int)aBuffer.Image.Height);
aBuffer.Image.CopyToBitmap(b);
BeginInvoke(new Action<Bitmap>(ChangeImage), b);
}
void ChangeImage(Bitmap b)
{
if (PictureBox.Image != null)
PictureBox.Dispose();
PictureBox.Image = b;
GC.Collect();//taking this away causes memory to leak rapidly.
}
}
}
It's very likely that somewhere in your code an Image such as a Bitmap is not being disposed. Bitmap extends Image which implements IDisposable which means you need to call Dispose() on it when you're done with it (often by wrapping it with a using statement). You aren't disposing the Bitmap or Image somewhere so the GC finalizes it when it can (or in this case when you explicitly invoke the GC).
Once the GC determines that a class is no longer referenced, it becomes available to clean up... Before cleaning it up, it checks for a finalizer. If a finalizer exists, the class is placed in a special GC finalizer queue that will run the finalizer before cleaning up the resources/memory. Most IDisposable classes have finalizers which allow the GC to do the Dispose() call work in case you forgot to manually dispose the class yourself. It seems that this is what is happening to your code, but without seeing ALL classes I can only guess what isn't disposed (and no idea where).
EDIT: I do have a guess though. I bet the PictureBox.Dispose() call does not dispose PictureBox.Image
If an object implements IDisposable then you should absolutely call Dispose on it but disposing an object doesn't release the memory it occupies. It releases things like, in this case, an image handle. Such resources have to be released first, before memory can be reclaimed, so disposing still helps.
When the GC runs, if an object hasn't been disposed then it must first finalise it, meaning that it must wait longer to reclaim the memory. If the object has been disposed, memory is reclaimed as soon as the GC runs.
The GC runs in the background though. If your application is busy allocating more and more memory then the GC never gets a chance to run and reclaim it, regardless of whether you dispose objects or not. In such cases, you need to invoke the GC explicitly from time to time. Creating multiple images is the most common scenario that requires explicit GC invocation.
It's worth noting that ALL objects remain in memory until the GC runs and cleans them up, whether the object implements IDisposable or not. You normally don't notice it though, because most apps have enough down-time to allow the GC to run implicitly and reclaim that memory. There's nothing special about your Bitmap objects in this regard.
You are disposing the picture box instead of the image. Even if that will dispose the image in the picture box, it will only do that the first time. After that the picture box is in a disposed state and calling Dispose again will do nothing.
You should get the image reference from the picture box and dispose it once it's not used any more:
void ChangeImage(Bitmap b) {
Image oldImage = PictureBox.Image;
PictureBox.Image = b;
if (oldImage != null) {
oldImage.Dispose();
}
}
A bitmap that isn't disposed correctly have to be finalized before it can be collected. There is a background thread that finalizes objects that needs to be collected, but if you abandon objects faster than that thread can take care of them, you will run out of memory.
When the bitmap is disposed correctly, it becomes a regular managed object that can be collected right away whenever the garbage collector wants to.

Categories