I am a newbie to C# and Threading and this is a very simple question, but has me really stuck. I did search on this site but could not find an answer similar to my scenario:
I have a method say Parent() and in that I create a typed list, every nth time I pass it off to a Task. I have the problem of when to clear the list and release the memory since it keeps growing. I tried clearing list at the end of the task, if I clear list with the Parent method, the list is empty in the thread.
Could someone help me? I know this is a very simple problem, but would appreciate the help.
public void Parent()
{
List<MyType> list = new List<MyType>();
for (int i = 0; i< N; i++)
{
list.Add(new MyType {Var = "blah"});
if ( i% 10 == 0) //every tentth time we send a task out tou a thread
{
Task.Factory.StartNew(() => WriteToDB(new List<MyType>(list)));
//here I am sending a new instance of the list
//Task.Factory.StartNew(() => WriteToDB((list)));
//here I am sending same instance
list.Clear();
//if I clear here the list sent to the WriteToDB is empty
//if I do not, the memory keeps growing up and crashes the app
}
private void WriteToDB(List<MyType> list)
{
//do some calculations with the list
//insert into db
list.Clear();
}
}
}
You've got a closure bug.
The lambda () => WriteToDB(new List<MyType>(list))
isn't executed until the new Task
starts.
This will sometimes be after your call to list.Clear()
.
The fix is to capture the copy of the list outside the lambda:
var chunk = new List<MyType>(list);
Task.Factory.StartNew(() => WriteToDB(chunk));
list.Clear();
Just create the new list before starting the thread:
var newList = new List<MyType>(list);
Task.Factory.StartNew(() => WriteToDB(newList));
list.Clear();
This way, the new list is ready before the new thread starts, so it's safe to immediately clear the original one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With