Ryan
Ryan

Reputation: 5546

working with threads - add to collection

List<int> data=new List<int>();
foreach(int id in ids){
    var myThread=new Thread(new ThreadStart(Work));
    myThread.Start(id);
}


Work(){
}

Method Work does some processing on the received id and then adds the result to the data list? How can I add data to the collection from each thread? How would my code look like? thanks

Upvotes: 1

Views: 1593

Answers (3)

Adeel
Adeel

Reputation: 19238

you can pass and retrieve data (using callbacks) from threads. See MSDN article.

Example:

    public class SomeClass
    {
        public static List<int> data = new List<int>();
        public static readonly object obj = new object();

        public void SomeMethod(int[] ids)
        {
            foreach (int id in ids)
            {
                Work w = new Work();
                w.Data = id;
                w.callback = ResultCallback; 
                var myThread = new Thread(new ThreadStart(w.DoWork));
                myThread.Start();
            }
        }

        public static void ResultCallback(int d)
        {        
            lock (obj)
            {        
                data.Add(d);
            }
        }

    }

    public delegate void ExampleCallback(int data); 
    class Work
    {
        public int Data { get; set; }
        public ExampleCallback callback;

        public void DoWork()
        {                
            Console.WriteLine("Instance thread procedure. Data={0}", Data);
            if (callback != null)
                callback(Data);
        }

    }

Upvotes: 0

Vlad
Vlad

Reputation: 35594

First of all, you need to protect your multithreaded access with a lock. Second, you need to pass the parameter to your thread (or use lambda which can capture the local variable; beware that if you capture loop variable, it will change the value during the loop, so you ought to have a local copy).

object collectionLock = new object();
List<int> data = new List<int>();

foreach (int id in ids)
{
    Thread t = new Thread(Worker);
    t.Start(id);
}

void Worker(object o)
{
    int id = (int)o;
    lock(collectionLock)
    {
        data.Add(id);
    }
}

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500675

If you're using .NET 4, I strongly suggest you use Parallel Extensions instead. For example:

var list = ids.AsParallel()
              .Select(Work)
              .ToList();

where Work is:

public int Work(int id)
{
    ...
}

so that it can receive the id appropriately. If you're not keen on the method conversion, you could add a lambda expression:

var list = ids.AsParallel()
              .Select(id => Work(id))
              .ToList();

Either way, this will avoid creating more threads than you really need, and deal with the thread safety side of things without you having to manage the locks yourself.

Upvotes: 8

Related Questions