Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing lists into a Task

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(); 
      }
     }
   }
like image 928
Santino Avatar asked Dec 01 '12 10:12

Santino


2 Answers

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();
like image 116
Nick Butler Avatar answered Oct 13 '22 23:10

Nick Butler


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.

like image 1
McGarnagle Avatar answered Oct 13 '22 23:10

McGarnagle