views:

101

answers:

4
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ThreadDemo
{
    class Program
    {
        static public  List<int> temp = new List<int >();
        static  public  List<Thread> worker = new List<Thread>();
        static public List<List<int>> Temporary = new List<List<int>>();
        static void Main(string[] args)
        {
            temp.add(20);
            temp.add(10);
            temp.add(5);
            foreach (int k in temp)
            {
                int z = 0;
                worker[z] = new Thread(() => { sample(k); });
                worker[z].Name = "Worker" + z.ToString();
                worker[z].Start();
                z++;
            }
        }
        public static void sample(int n)
        {
            List<int> local = new List<int>();
            for (int i = 0; i < n; i++)
            {
                local.Add(i);
            }
            Temporary.Add(local);
        }
    }
}

in this program i have the problem in thread when start the foreach loop in main program creates the three thread and also starts that thread.In that first thread operation is longer than other so it will take some time but other thread completed before the first due to this order in temporary is changed .i need temporary list order as same as temp list order.how can achieve this using thread

+1  A: 

At first, all your threads are access Temporary collection, and because List is not thread safe you should synch your threads to work correctly, and the second, You have no guaranty that the first thread will finish first if the first starts first, it depends how core will schedule threads. To achieve what you want you can use thread synchronization mechanisms

ArsenMkrt
+8  A: 

There are three problems. First, variable capture:

foreach (int k in temp)
{
    int z = 0;
    worker[z] = new Thread(() => { sample(k); });
    ...
}

That's capturing the variable k in the lambda expression, not the value of k. The solution is to take a copy:

foreach (int k in temp)
{
    int z = 0;
    int copy = k;
    worker[z] = new Thread(() => { sample(copy); });
    ...
}

See Eric Lippert's blog post for more information.

Secondly, you're always populating worker[0] because z will always be 0. If you want to populate other elements, you'll need to declare z outside. Alternatively, you could just add to the list.

Thirdly, there's the problem of not knowing the ordering of the results. The easiest way of fixing this is actually to turn Temporary into an array. Again, capture a copy of the variable to keep the right position. As ArsenMkrt says, you'll also need to update a list, which will involve locking.

Are you using .NET 4.0 (or could you)? Parallel Extensions makes all of this much, much simpler.

Jon Skeet
Ah, variable capture... bitten me a few times before. +1 just for pointing that out!
Pwninstein
@jon Skeet thank you for Your reply i like to know bit clear about ur solution
ratty
@ratty: Which solution - modifying yours, or using Parallel Extensions? The latter would be *much* simpler.
Jon Skeet
parallel extensions and i like to know how the locks help for me in this problem
ratty
A: 

If you need the threads' results in order, you should probably either pass them your z somehow, or have them return a result and join each of the threads in order in the main thread.

Other than that, you may be kinda screwed. Threads are, by their nature, prone to run at exactly the wrong time no matter what you need to do. You can't rely on them to start or stop exactly when you please; if you could, whole classes of concurrency issues would just go away.

I'd recommend you use threads sparingly. On single-core, single-CPU machines, your threading example would run slower than a decently coded solution without threading, because there's overhead involved in starting a thread. The only time i've ever seen threads be really useful, are times when you'd actually need to be appearing to do two things at once. Like keeping your UI working while you wait for input or do some arbitrarily big job in the background. Having threads for the sake of having them will end up driving you crazy.

cHao
+1  A: 

Here is a quick stab at your code:

class Program
{
    static public List<int> temp = new List<int >();
    static public List<Thread> worker = new List<Thread>();
    static public List<List<int>> temporary = new List<List<int>>();
    static public object sync = new object();

    static void Main(string[] args)
    {
        temp.add(20);
        temp.add(10);
        temp.add(5);

        // Add a corresponding number of lists
        for( int i = 0; i < temp.Count; ++i)
        {
            temporary.Add(new List<int>);
        }

        // As Jon Skeet mentioned, z must be declared outside the for loop
        int z = 0;
        foreach (int k in temp)
        {
            // As Jon Skeet mentioned, you need to capture the value of k
            int copy = k;

            Thread t = new Thread(() => { Sample(copy, z); });
            t.Name = "Worker" + z.ToString();

            // set the thread to background, so your thread is 
            // properly closed when your application closes.
            t.IsBackground = true; 
            t.Start();

            // Calling worker[z] will always going to be out of bounds
            // because you didn't add anything to to the worker list,
            // therefore you just need to add the thread to the worker
            // list. Note that you're not doing anything with the worker
            // list, so you might as well not have it at all.
            worker.Add(t);
            z++;
        }
    }

    // Supply the order of your array
    public static void Sample(int n, int order)
    { 
        for (int i = 0; i < n; i++)
        {
            // Technically in this particular case you don't need to 
            // synchronize, but it doesn't hurt to know how to do it.
            lock(sync)
            {
                temporary[order].Add(i);
            }
        }
}

Now the temporary list should contain the other lists in the correct order (same as your tmp order). Your title does mention scheduling, but I'm not sure why you need scheduling here or what exactly you're trying to learn about scheduling.

Lirik
Thank you for YOur answer i think this will help me
ratty
@ratty, let me know if you're not understanding some part of it.
Lirik