In my app(music player) i have feature called "Game Mode" which stops every background operations except playing music and i wanna free some memory too.
E.g.
I have Background Image on Base Grid in my window which i set that way
BaseGrid.Background = new ImageBrush("the image");
In GameMode method i do something like this
BaseGrid.Background = null;
GC.Collect();
but it didnt free any memory when first time called, when i call the method second time it works, or if i paste the MessageBox.Show method between nulling and GC.Collect it works too.
So my question is.
Is setting Background to null Asynchronous operation that takes some time and GC.Collect didnt see unused object when its called so early after nulling or what another problem it can be?
When ever you call
GC.Collect();
you should call
GC.WaitForPendingFinalizer()
also
Use:
GC.WaitForPendingFinalizer();
Related
I am working on feedback application which have lots of form open and close operation. I noticed few changes in memory changes in my application when i start my application it takes 25 MB. With each feedback user give it increases 3 MB in memory usage. On every form i had used this.close() when it jumps from one to other or there is any close operation. What can be the possible reason of memory increases.
Do i need to call garbage collector manually, as everyone says its not good practice.
In this i am using dual monitor scenario in which application take snapshot of secondary screen after each 500 ms and shows it on primary screen. For this I am using the code shown below:
public EntryForm()
{
sc = Screen.AllScreens;
dbDms = new HondaDb(UtilityFunctions.getServerConnection());
db = new HondaDb(UtilityFunctions.getClientConnection());
bmpScreenshot = new Bitmap(sc[1].Bounds.Width,
sc[1].Bounds.Height,
PixelFormat.Format32bppArgb);
Create a graphics object from the bitmap.
gfxScreenshot = Graphics.FromImage(bmpScreenshot);
Timer timerClientScreen = new Timer();
timerClientScreen.Interval = 500;
timerClientScreen.Enabled = false;
timerClientScreen.Start();
timerClientScreen.Tick += new EventHandler(timer_TickClient);
}
void timer_TickClient(object sender, EventArgs e)
{
// Take the screenshot from the upper left corner to the right bottom corner.
gfxScreenshot.CopyFromScreen(sc[1].Bounds.X, sc[1].Bounds.Y,
0, 0, sc[1].Bounds.Size, CopyPixelOperation.SourceCopy);
// Save the screenshot to the specified path that the user has chosen.
pictureBoxClient.Image = bmpScreenshot;
}
For closing of form on open of other I am using the code below
formOpen.show();
formClose.Close();
Suggest me how can I save memory usage.
It does, but just your UI objects. It isn't automatic for the variables you use. In an app like this, using big objects that take very little GC heap space but lots of unmanaged resources, the garbage collector doesn't typically run often enough to keep you out of trouble. You have to help and explicitly dispose the objects so you don't leave it up to the GC to take care of the job.
It may take too long for it to start running, you can build up a lot of unmanaged memory usage before it gets to run the finalizers. Potentially crashing your program with OOM, although you are still very far removed from that problem. Right now you are just running "heavy".
Add an event handler for the FormClosed event. You need to call the Dispose() method on the gfxScreenshot and bmpScreenshot objects. And surely those HondaDb objects need some kind of cleanup as well.
Do not assume that will instantly solve memory usage increments, the GC is not eager to release address space back to the operating system. Keeping it around instead with the assumption that you are likely going to have a need for it soon. The proper usage pattern is it stabilizing after a while at a reasonable number, then suddenly dropping and building back up. A saw-tooth pattern. Write a little unit test that calls creates and destroys your form object repeatedly, ensuring that it does the non-trivial jobs of taking the screenshot and accessing the dbase. Now you know with confidence that you don't have a run-away leak problem.
No, when you call Form.Close() you are just telling to close the form. the object is still there in memory and if you have a reference to it, it will be there until you have held that reference.
.NET has automatic garbage collection mechanism which collect objects that are garbage (you have no reference to them and they can not be accessed). So objects are removed from memory when they become garbage and .NET garbage collector starts it works. You can force executing garbage collector by calling GC.Collect().
More about GC
Have a look at this MSDN Thread. It's about dispoable Windows, this should release all ressource held by a an instance of a class. Then the garbage collector should do it's work.
Wondering if someone can answer something that has stumped me.
I have a Timer that sets a variable to let some other threads know when to stop execution (the length is hard coded for this example)
Timer endProcessingThread = new Timer(x => _endOfProcessingTimeHasElapsed = true, null, 10000, 0);
I don't ever join on the thread or use the timers variable name for anything so I 'cleaned' it up to say:
new Timer(x => _endOfProcessingTimeHasElapsed = true, null, 10000, 0);
This compiles fine but the thread never executes.
Anyone know why?
My guess is that the Timer is going out of scope and being GCed before the 10 seconds are up. From MSDN:
As long as you are using a Timer, you must keep a reference to it. As with any managed object, a Timer is subject to garbage collection when there are no references to it. The fact that a Timer is still active does not prevent it from being collected.
The solution is to keep that reference at whatever code level will still be around in 10 seconds (or whenever) by assigning it to some class or form property/field.
First of all: Timer is IDisposable, so that you should use the timer’s variable name, at least to dispose it properly.
And: Since you do not keep any reference to the created instance, it is eligible for garbage collection. And since the internals of the Timer use a finalizer, the finalizer gets called and the timer gets deleted before it had a chance to fire. (Note that just keeping a reference in a named local variable as in your first case is not enough, the compiler might notice the variable is not used at all and garbage collect the instance anyway.)
Solution: Keep the reference and call Dispose() as soon as you finished using it.
This compiles fine but the thread never executes.
The anonymous Timer is possibly cleaned up by the Garbage collector before it triggers.
See this SO question.
It could be that since you never hold a reference to the object you create, it either gets optimized away immediately (no lvalue) or it simply get GC'd and never executes.
FWIW doesn't that class implement IDisposable? If so, you should be using a using statement or calling dispose.
I had another question on my PictureBox calls giving me 3 kinds of errors, some great answers came in particularly from Conrad Frix. So it led me to figure out where my problem is, but now to fix it I am not 100% sure on.
Basically I have a Windows Form timer that is checking for some event to be true, if it is, then it tells the system to send some data out 2 seconds after said event (a value ) is past some threshold.
I think all the timers I have is creating a nasty race condition with my PictureBox that I use in several places to get the image from:
new Bitmap(myPicBox.Image);
etc...
I read somewhere that the interval on the timer should be at least 50. Set that from 33. I found out I can do a picCapture.InvokeRequired to see if its going to basically die. I know I need to use a delegate but only ever used those to set something... not to get an image from.... not sure how to set that up... I know what is indeed causing it, it is this combination of code:
private void timer1_Tick(object sender, EventArgs e)
{
if(someCOnditionTrue)
{
TimerCallback tc = new TimerCallback(sendDataFast); //only
//doing all this so i can have the method run two seconds after
// the condition is detected to be true.
System.Threading.Timer t = new System.Threading.Timer(tc, null, 2000, Timeout.Infinite);
}
}
void sendDataFast(Object stateObject)
{
//using this so the execution is not haulted while the sending of data takes place.
EmergencyDelegate delEmergency =
new EmergencyDelegate(mic.sendEmergencyData);
Image imgclone;
if (picCapture.InvokeRequired)
{
Console.WriteLine("HFS Batman! its going to die ");
}
lock (lockObject2) //i admit no clue what im doing here and doesn't seem to help.
{
Image img = picCapture.Image;
imgclone = (Image)img.Clone();
}
delEmergency.BeginInvoke(imgclone, null, null); //deep in the call to
//sendEmergencyData i get the **ParameterNotValid** almost everytime.
imgclone.Dispose(); //to free memory?
}
As per my previous question, no longer seem to get the memory issues or other errors in the timer1_tick event... (out of memory error was one).
I think the biggest issue is how can I handle the picCapture.InvokeRequired when I need its image data? I am certain its the threading timer call inside the timer1_click I do that is causing this....
As its name suggests, InvokeRequired means you need to call Invoke (or BeginInvoke) when accessing the control.
Note that this is Control.Invoke/Control.BeginInvoke, not the Invoke/BeginInvoke which are present in delegates... although you'll need a delegate in order to call Invoke/BeginInvoke, just to add more confusion to the mix.
See the Windows Forms section of my threading tutorial for more details. The overall tutorial could do with updating, but I believe this bit is okay. In other situations you may also want to consider using BackgroundWorker, but I don't think that's likely to be relevant for you in this particular case.
I think that you have got a wrong understanding about InvokeRequired. InvokeRequired indicates that the current thread is not the same as the UI thread and it will not be safe to access the control state now. If such is the case then you have to use Control.Invoke to marshal call to the UI thread and then access the control state. Read here on MSDN for more info.
In your case, unless the PictureBox image is changing, I would suggest that you rather make a clone of the image upfront and use that. Otherwise you need to use Control.Invoke.
You've got too many threads going to bring this to a good end. Both the Timer and the delegate's BeginInvoke() method will use a threadpool thread. The problem is that the PictureBox.Image property is only partially thread-safe. It can be accessed by only one thread at a time. Your code will die with an exception when the image is painted by the UI thread at the exact same time your code is calling the Clone() method.
Your lock statement doesn't solve the problem, the PictureBox is accessing the Image property without using that same lock. I would strongly recommend getting rid of the threading first, use a System.Windows.Forms.Timer instead of a System.Threading.Timer. It's Tick event is raised on the UI thread. That will however make the UI thread unresponsive while the event is running, it depends how long it takes whether that's noticeable to the user. More than, say, 100 milliseconds gets to be a problem.
The only other approach is to try to make the PictureBox control thread-safe. That's possible to some degree. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form, replacing the existing PB. Beware that this is only a partial solution, displaying an animated GIF or using the ImageLocation property will still bomb. Use the provided Clone method instead of calling Clone on the Image property.
using System;
using System.Drawing;
using System.Windows.Forms;
class MyPictureBox : PictureBox {
private object locker = new object();
public new Image Image {
get { return base.Image; }
set { lock (locker) { base.Image = value; } }
}
public Image Clone() {
lock (locker) {
return (this.Image != null) ? (Image)this.Image.Clone() : null;
}
}
protected override void OnPaint(PaintEventArgs pe) {
lock (locker) {
base.OnPaint(pe);
}
}
}
I'm getting in trouble. I'm trying to emulate the call Application.Run using Application.DoEvents... this sounds bad, and then I accept also alternative solutions to my question...
I have to handle a message pump like Application.Run does, but I need to execute code before and after the message handling. Here is the main significant snippet of code.
// Create barrier (multiple kernels synchronization)
sKernelBarrier = new KernelBarrier(sKernels.Count);
foreach (RenderKernel k in sKernels) {
// Create rendering contexts (one for each kernel)
k.CreateRenderContext();
// Start render kernel kernels
k.mThread = new Thread(RenderKernelMain);
k.mThread.Start(k);
}
while (sKernelBarrier.KernelCount > 0) {
// Wait untill all kernel loops has finished
sKernelBarrier.WaitKernelBarrier();
// Do application events
Application.DoEvents();
// Execute shared context services
foreach (RenderKernelContextService s in sContextServices)
s.Execute(sSharedContext);
// Next kernel render loop
sKernelBarrier.ReleaseKernelBarrier();
}
This snippet of code is execute by the Main routine. Pratically I have a list of Kernel classes, which runs in separate threads, these threads handle a Form for rendering in OpenGL. I need to synchronize all the Kernel threads using a barrier, and this work perfectly.
Of course, I need to handle Form messages in the main thread (Main routine), for every Form created, and indeed I call Application.DoEvents() to do the job.
Now I have to modify the snippet above to have a common Form (simple dialog box) without consuming the 100% of CPU calling Application.DoEvents(), as Application.Run does.
The goal should be to have the snippet above handle messages when arrives, and issue a rendering (releasing the barrier) only when necessary, without trying to get the maximum FPS; there should be the possibility to switch to a strict loop to render as much as possible.
How could it be possible?
Note: the snippet above must be executed in the Main routine, since the OpenGL context is created on the main thread. Moving the snippet in a separated thread and calling Application.Run is quite unstable and buggy...
There isn't anything fundamentally wrong with calling Application.DoEvents() in a loop. That's what Form.ShowDialog() does. It takes counter-measures to ensure the user cannot get into trouble: it disables all windows other than the dialog so the user cannot exit the application or start the dialog again.
You'll need to create your own, set a global flag that indicates that your main window was closed so you can immediately exit the loop without calling any more code when the rug is pulled out from under you.
You'll need to yield the processor to avoid 100% CPU load. The easiest way to do that is by calling Thread.Sleep(1). Check my answer in this thread for an example.
Don't do it - this stuff is pretty complex and I'm pretty sure you get nothing but trouble for implementing it yourself.
Can't you use Application.AddMessageFilter() to implement what you need?
If you're going to build a message loop like this, you should PInvoke the actual Win32 message handling functions (which is all that Application.Run is doing behind the scenes -- it has an internal class called UnSafeNativeMethods that maps a bunch of them).
If you don't need to keep processing between message calls -- in other words, if it's safe for your thread to sleep when it's not actively handling a message -- then bind WaitMessage from User32.dll and put it in a loop like:
while (WaitMessage())
{
Application.DoEvents();
}
If you need more help let me know. I'm in the middle of a VS reinstall right now or I'd post a sample application showing how to do the binding and PInvoke.
I have a form being displayed by a static method.
This static method calls ShowDialog on the form:
//Static method on LockWaitForm
public static LockDetails Lock(string lockedMessage, object[] params parameters)
{
using (LockWaitForm form = new LockWaitForm(parameters))
{
form._lockedMessage.Text = lockedMessage;
DialogResult result = form.ShowDialog();
return new LockDetails (form._lockStatus, form._lock);
}
}
What I want is the OnLoad method of the dialog to wait up to one second before it shows, so it will only display if a lock on a record cannot be achieved after 1 second. It will happily drop out before one second if a lock is obtained before 1 second, setting its DialogResult to OK.
All functionality works fine except the hiding of the Dialog box for 1 second. All 'Visible = false' calls are ignored, and I can kind of understand why they would do that. The problem with this is that a false 'record is locked' will flash up for a sub second every time the form is used and a lock can be obtained without an issue.
I can figure out a few hacky ways to delay the visibility of the dialog box
Set Opacity to 0% - this does not work for Remote Desktop Connections
Have the form only be initialized by the static method once the 1 second has elapsed. This is promising, but requires a lot of repeated static vs non static code to handle the setup and disposal of the lock, and still feels a bit hacky.
Is it possible to limit the display of a Modal Dialog called through ShowDialog? I am reluctantly happy to PInvoke at this point (though I do want to limit non-64bit code for future requirements)
EDIT
By moving my acquire lock code to the form's constructor instead of Load, I can keep the locking code in one place, and just wait while the form's lock status is in a Waiting state before calling ShowDialog. Still feels dirty, but the cleanest method so far
I would refactor the application to not even display the modal dialog until the lock process has failed to achieve a lock for one second.
Not sure this would work, but: in your LockWaitForm, override ShowDialog() with your own version that calls the code to acquire a lock (or whatever it's doing), and then if more than 1 second passes, call this.ShowDialog() (the real one). This should allow you to only change the code in LockWaitForm, and not anywhere else.
Sorry, my laptop with Visual Studio is in a friend's trunk right now, so I can't check if this is possible.
What sort of lock? Just a normal thread lock? Can you just use Monitor.TryEnter?
If it returns false, the lock is busy and you can pop some sort of retry/cancel lock-waiting window.
If it's true though, just proceed with life as normal.
As a general comment, I really agree with Eric J that you should not be displaying the form until the lock has failed. It seems awkward to be using the error dialog to perform the ordinary workflow, and trying to secretly hide it in the non-error case.
Instead, you should have a proper workflow doing the lock entirely outside the error dialog, and pop the dialog only on the error workflow.