Q:

Prime number generator using threads

I am trying to generate prime numbers using Threads in C#. The user has to input the number of threads to be generated. I have the following issues when I run the code:

I get Index out of range exception sometimes if I tried to use more than one thread. If I try again, it works.
Each of the thread is calculating the same values. For e.g If I input two threads to generate prime numbers between 2 and 100 (both included), I get the following output.

2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
I have gone through the following post. But I cannot resolve these issues. I am new to Threading concepts. How to solve these issues?
Simple prime number program - Weird issue with threads C#
This is my code
class Program {
  const int min = 2;
  const int max = 100;
  static List<int> primes = new List<int> ();

  static void GeneratePrimes (int start, int range) {
     bool isPrime = true;
     int end = start + range;
     for (int i = start; i <= end; i++) {
        for (int j = start; j <= end; j++) {
           if (i != j && i % j == 0) {
              isPrime = false;
              break;
           }
        }
        if (isPrime) {
           primes.Add (i);
        }
        isPrime = true;
     }
  }

  static void Main (string[] args) {
     int threadCount = Convert.ToInt32 (Console.ReadLine ());
     Thread[] threads = new Thread[threadCount];
     int range = (max - min) / threadCount;
     int start = min;         
     for (int i = 0; i < threadCount; i++) {
        int startl = start;
        threads[i] = new Thread(new ThreadStart(() => GeneratePrimes(start, range)));
        startl += range;
        threads[i].Start ();            
     }
     for (int i = 0; i < threadCount; i++)
        threads[i].Join();
     PrintPrimes();
  }

  static void PrintPrimes () {
     foreach (int i in primes)
        Console.WriteLine (i);
  }
}

UPDATE
I made the changes as suggested in the answer by NikolayKondratyev. But now I have duplicate values in the list when I use more threads (>5)

A:

First problem is that you have wrong start for the threads. Thread creation should be
for (int i = 0; i < threadCount; i++) {
    var startl = start;
    threads[i] = new Thread(new ThreadStart(() => GeneratePrimes(startl, range)));
    start += range;
    threads[i].Start();
}

Also List is not thread safe, insted use Thread-Safe Collections. 
For example ConcurrentQueue and its method Enqueue.
There is also a problem with for conditions, they should be like follows
for (var i = start; i < end; i++)
{
    for (var j = min; j < end; j++)
    {
        ...
    }
}

And you can optimize the it with
for (var j = min; j < Math.Sqrt(end); j++)

Another problem is that you have wrong range, there can be unprocessed values because start + range 
is less than max for 5 threads for example. So for the last thread we need to add (max - min)%threadCount
more values. Here is the full code
class Program
{
    private const int min = 2;
    private const int max = 100;
    private static readonly ConcurrentQueue<int> primes = new ConcurrentQueue<int>();

    private static void GeneratePrimes(int start, int range)
    {
        var isPrime = true;
        var end = start + range;
        for (var i = start; i < end; i++)
        {
            for (var j = min; j < Math.Sqrt(end); j++)
            {
                if (i != j && i%j == 0)
                {
                    isPrime = false;
                    break;
                }
            }
            if (isPrime)
            {
                primes.Enqueue(i);
            }
            isPrime = true;
        }
    }

    private static void Main(string[] args)
    {
        var threadCount = Convert.ToInt32(Console.ReadLine());
        var threads = new Thread[threadCount];
        var range = (max - min)/threadCount;
        var start = min;
        for (var i = 0; i < threadCount - 1; i++)
        {
            var startl = start;
            threads[i] = new Thread(() => GeneratePrimes(startl, range));
            start += range;
            threads[i].Start();
        }
        threads[threadCount - 1] = new Thread(() => GeneratePrimes(start, range + (max - min)%threadCount));
        threads[threadCount - 1].Start();

        for (var i = 0; i < threadCount; i++)
            threads[i].Join();
        PrintPrimes();
    }

    private static void PrintPrimes()
    {
        foreach (var i in primes)
            Console.WriteLine(i);
    }
}

