Releasing The Memory Used By Objects And Lists - c#

I am trying to understand Garbage Collection process, and I think I got the idea. But when I works on some codes, It doesn't work as I expected.
In the code below, I just created 1.000.000 object and added them to a list. After a while, there is no object but memory stucks and not decreasing. How can I achieve to release the memory after all objects removed?
Thanks
private void button1_Click(object sender, EventArgs e)
{
List<Test> tesst = new List<Test>();
for (long i = 0; i < 1000000; i++)
{
using (Test test = new Test())
{
test.LongObj = i;
test.StrObj = i.ToString();
test.DecObj = Convert.ToDecimal(i);
tesst.Add(test);
}
}
Process proc = Process.GetCurrentProcess();
proc.Refresh();
label1.Text = Test.counter.ToString();
label2.Text = (proc.PrivateMemorySize64 / 1048576).ToString();
for (int i = 0; i < tesst.Count; i++)
{
tesst[i] = null;
}
tesst.Clear();
tesst = null;
}
private void button2_Click(object sender, EventArgs e)
{
Process proc = Process.GetCurrentProcess();
proc.Refresh();
label1.Text = Test.counter.ToString();
label2.Text = (proc.PrivateMemorySize64 / 1048576).ToString();
}
And the sample class
public class Test : IDisposable
{
public static long counter = 0;
public long LongObj { get; set; }
public string StrObj { get; set; }
public decimal DecObj { get; set; }
public Test()
{
Interlocked.Increment(ref counter);
}
~Test()
{
Interlocked.Decrement(ref counter);
}
public void Dispose()
{
}
}

Why exactly are you trying to release the memory manually? There are valid reasons, but I want to make sure you are in a situation that requires it.
You can force a garbage collection by calling GC.Collect() and optionally with a parameter telling it which generation to collect. You can read more about this here and it includes a similar test to what you are attempting to do.

How can I achieve to release the memory after all objects removed?
You don't, you let the GC do its job. Forcing the garbage collection (using System.GC.Collect()) is almost always a bad idea.

This really seems like a scenario where you need to rethink your process. I don't think this is a job for manually interacting with GC. Maybe if you post some of your code in a different question people can throw out some ideas on a different way to solve the problem?

Related

Refresh UI from a method running asyncronously on another project

I had a winform using a method on another project thought a DLL, test, count and returns 2 values (good files and bad files) and show up on the winforms those 2 results once done.
Ive been asked to improve that winform to show up results in real time, since the work and the test can take up to 30mins, but ive been struggling since i'm beginning in async programmation.
Ive tried to call function with out or ref, without success. As far i tried, i can refresh in real time a local variable, but not one running in the method out of the winform project.
Winform :
public static int goodfiles { get; set; }
public static int badfiles { get; set; }
Task workControl;
Task refreshControl;
private async void Winform_Load(object sender, EventArgs e)
{
myprogressBar.Style = ProgressBarStyle.Marquee;
workControl = Task.Run(() => WorkMethod());
refreshControl = Task.Run(() => RefreshMethod());
await executerControl.ConfigureAwait(true);
}
private void RefreshMethod()
{
while (!workControl.IsCompleted)
{
label1.Invoke(new MethodInvoker(delegate
{
label1.Text = goodfiles.ToString();
label2.Text = badfiles.ToString();
}
}
}
private void WorkMethod()
{
goodfiles = 0;
badfiles = 0;
var Work = new WorkClass();
Work.ControlFiles(goodfiles, badfiles);
}
Class library project
public class WorkClass
{
public void ControlFiles(int goodfiles, int badfiles)
{
//Do stuff
var Test = new TestClass();
Test.TestFiles(goodfiles, badfiles);
}
}
public class TestClass
{
public void TestFiles(int goodfiles, int badfiles)
{
//Test files
if(stuff) goodfiles++;
else badfiles++;
}
}
I know it's maybe far from being the prefect architecture, but I have to deal with it.
Is it technically possible, difficult or just impossible to do? Or am I missing something obvious ?
You need to use the same fields from the worker thread and UI thread. The best way is to put them in a shared object. This might be the work-class, but you could also create a separate object that is given as a parameter to the actual work-method. I recommend against using any mutable static fields.
public class WorkClass
{
public volatile int GoodFiles;
public volatile int BadFiles;
public void ControlFiles()
{
//Test files
if (stuff) GoodFiles++;
else BadFiles++;
}
}
and call it like
WorkClass myWork;
private async void Winform_Load(object sender, EventArgs e)
{
myWork = new WorkClass();
workControl = Task.Run(() => myWork.ControlFiles());
}
To check the progress I would recommend a timer. Set it to run however often you want, and update the labels from the myWork-object when event handler for the Tick-event. You can await the workControl-task and stop the timer when the task is done.
It depends on how coupled or uncoupled you want your code to be.
In most cases, the Progress class is a good choice.
Here's an article from Stephen Cleary on the subject: Reporting Progress from Async Tasks

Threading.Timer prevents GC collection

I'm having a memory leak problem, and I'm wondering if anyone can tell me what I'm doing wrong (or what Microsoft bug I missed). Below is a sample application that demonstrates the problem. Call TestCollectTimer.Test() to run the sample.
The problem is, no matter how many "MyTimerData" are created, or how many times GC.Collect() is called, the finalizer of MyTimerData is never called until the application shuts down.
class TestCollectTimer
{
public static void Test()
{
for (int index_A = 0; index_A < 100000; index_A++)
{
MyTimerData mtd = new MyTimerData();
mtd = null;
}
GC.Collect();
Thread.Sleep(2000);
GC.Collect();
Form f = new Form();
f.ShowDialog();
}
}
class MyTimerData
{
public System.Threading.Timer m_timer;
public MyTimerData()
{
this.m_timer = new System.Threading.Timer(
new System.Threading.TimerCallback(this.TimerCall),
null,
System.Threading.Timeout.Infinite,
System.Threading.Timeout.Infinite);
}
~MyTimerData()
{
MessageBox.Show("Collect My Timer Data");
}
public void TimerCall(object o) { }
}
Thankyou for your help
In debug mode, all local variables' scopes are artificially extended to the end of their enclosing methods, so they won't be collected before you've finished inspecting them in the debugger.
Your code works as expected when compiled in Release mode and run with no debugger attached.
You can also just move your for-loop into its own method, and then your timers will be eligible for collection after it returns, even in debug mode.
What about disposing your timer?
class TestCollectTimer
{
public static void Test()
{
for (int index_A = 0; index_A < 100000; index_A++)
{
using(MyTimerData mtd = new MyTimerData())
{
//do your stuff here
}
}
GC.Collect();
Form f = new Form();
f.ShowDialog();
}
}
class MyTimerData : IDisposable
{
public System.Threading.Timer m_timer;
public MyTimerData()
{
this.m_timer = new System.Threading.Timer(
new System.Threading.TimerCallback(this.TimerCall),
null,
System.Threading.Timeout.Infinite,
System.Threading.Timeout.Infinite);
}
public void TimerCall(object o) { }
public void Dispose()
{
Dispose(true);
}
protected void Dispose(bool disposing)
{
m_timer.Dispose();
GC.SuppressFinalize(this);
}
}
You may look the rule CA1001: http://msdn.microsoft.com/en-us/library/ms182172.aspx

C# using lock practice

I have critical section in my application which contains a lot of code:
which is better way to locking access in threadMethod:
A) lock all block:
private object locker = new object();
private void threadMethod()
{
while(true)
{
lock(locker)
{
// do work - a lot of code here
}
Thread.Sleep(2000);
}
}
B) Use additional locked access member canWork:
private static object locker = new object();
private bool canWork;
private bool CanWork
{
get { lock(locker) { return this.canWork; } }
set { lock(locker) { this.canWork = value; } }
}
private void threadMethod()
{
while(true)
{
if(CanWork)
{
// do work - a lot of code here
}
Thread.Sleep(2000);
}
}
and somewhere in code
CanWork = false;
Neither is particularly good.
The first has the disadvantage that you hold the lock for a long time.
The second has the disadvantage that the state can change after you check it.
Instead try to pass immutable arguments to your method (for example a copy of the data). You will probably still need to lock for constructing the arguments and for collecting the results but this is hopefully a much shorter period of time.
The second approach will likely lead to race conditions. Can your "a lot of code" be separated in several critical/non critical chunks?
I would use the Monitor instead. Plus do you really want while(true) because this will repeat forever?
private object syncObject = new object();
private void threadMethod()
{
bool tryToRun = true;
while(tryToRun)
{
if(Monitor.TryEnter(syncObject))
{
tryToRun = false;
// do work - a lot of code here
Monitor.Exit(syncObject);
}
else
{
Thread.Sleep(2000); // Possibly knock this up the how long you expect the lock to be held for.
}
}
}
est link:
http://msdn.microsoft.com/en-us/magazine/cc188793.aspx#fig7
Best usage is
- declare a new private sync object
- use "lock(synObject) { code here ... }

using Timer to know the age of an object

I am writing a class named Food. I considered a field “int cookingTime” to see how long each instance of this class has been existed. I assumed I should use the Timer class. I wrote the following piece of code but it did not work. I am not sure if my approach is correct . I really appreciate any help.
Class Food
{
private System.Timers.Timer timerClock = new System.Timers.Timer();
static int cookingTime = 0;
public Food()
{
this.timerClock.Elapsed += new System.Timers.ElapsedEventHandler(process);
this.timerClock.Interval = 1000;
this.timerClock.Enabled = true;
}
static void process(Object myObject, EventArgs myEventArgs)
{
cookingTime += 1;
}
}
How about saving the timestamp of the creation of the object? Then just subtrackt that from Now() when you want to know how long the object has existed.
Why not use System.Diagnostics.Stopwatch?
class Food
{
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
public TimeSpan CookingTime
{
get { return _stopwatch.Elapsed; }
}
}
I notice that your cookingTime field is static. If you are somehow totalling the times of multiple foods, then you might keep a list (static or otherwise) of Stopwatches, and whenever you need to know the total time, you could sum them all together.

Limit the Number of Created Processes

I have two classes: Action class, that has a method for executing VBScript files, and Item class that contains a list of Action instances. My problem is that I want to limit the number of VBScript files that can be run at the same time. I have no experience with this, and I have googled and searched around, but found nothing. My only idea of how to do is is presented here:
using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
namespace Test
{
public class Action
{
public string Script;
public static int Limit;
public static int ActiveCount = 0;
public Process process = new Process();
public Action(string script)
{
Script = script;
}
public void Execute()
{
process.EnableRaisingEvents = true;
process.Exited += new EventHandler(Handler);
try
{
if (ActiveCount < Limit)
{
process = Process.Start(
"c:\\windows\\system32\\wscript.exe",
"\"" + Script + "\"");
ActiveCount++;
}
}
catch(Win32Exception e)
{
}
}
private void Handler(
object sender, EventArgs e)
{
ActiveCount--;
}
}
public class Item
{
public ArrayList Actions = new ArrayList();
}
class Program
{
static void Main()
{
Action.Limit = 5;
Item item = new Item();
item.Actions.Add(
new Action("C:\\Scripts\\Test_1.vbs"));
for (int i = 0; i < 10; i++)
{
foreach (Action action in item.Actions)
{
action.Execute();
Console.WriteLine(Action.ActiveCount);
}
}
}
}
}
The requirement of limiting the number of created processes seems common to me, but as I said, I haven't been able to find any samples I could build on. My question is: what is the common or usual way of doing this? (I also haven't been able to find any samples here on StackOverFlow, so if there are any, please post the link). Any hint or a link is welcome.
Well what you've got will work.
I'm not sure what the fact that you can't find more information tells you.
It's either that you're trying to solve a non-problem - but if your scripts are large and complex or need access to shared resources then limiting the number that run would seem to be a good idea; or it's that your solution is the right one and it's so trivial no one else has thought to raise it.

Categories