1

I am writing a multithreaded application it is windows service. I have 20 folders. I create 15 threads onstart method. I want to achieve that; 15 threads go to folders 1,2,3,...,15 sequentially. When one thread finished, it creates another thread. This created thread must go 16.th folder. It must not go to working folders. How can I do this? That is, how can I be sure that two threads do not go the same folder?

user3894737
  • 31
  • 1
  • 1
  • 10
  • do you mean 15 threads go to every 15 folder or one folder per thread.. if the latter, why do you need threads for what would become synchronous? – Sayse Sep 03 '14 at 12:36
  • I mean one folder per thread. – user3894737 Sep 03 '14 at 12:39
  • 1
    just pass a parameter for determining the number. Or use parallelfor – Sebastian L Sep 03 '14 at 12:43
  • creating 15 threads is impossible in parallel.for I think. – user3894737 Sep 03 '14 at 13:36
  • Yes it might be that my solution with Task doesn't really run on 15 threads as well. By default Tasks uses the threadpool which has a limited number of threads (although you can set your own number of max threads). Anyway you would be able to have a static counter for the folder names even if you created the Threads yourself. – mortb Sep 03 '14 at 13:47

2 Answers2

1

Could you not just have a static variable that would be a counter for the folder name?

Something like:

private static int _folderNameCounter = 0;
private static readonly object _padlock = new object();
public static int GetFolderCounter()
{
     lock(_padlock)
     {
         _folderNameCounter++;
         return _folderNameCounter;
     }
}

public static void Main()
{
        for(int i = 0; i < 20; i++)
        {

            Task.Factory.StartNew(() => 
             {
                var path = @"c:\temp\" + GetFolderCounter();
                Directory.CreateDirectory(path);
                // add your own code for the thread here
             });
        }

}
mortb
  • 9,361
  • 3
  • 26
  • 44
  • No, it does not really start 20 threads. The taskscheduler determines how many. If you "explictly" want to start 20 threads you can specify the TaskCreationOptions.LongRunning option to Task.Factory.StartNew , (it does not seem 100% guaranteed that you get that many threads): http://stackoverflow.com/questions/13570579/is-it-possible-always-to-force-a-new-thread-with-task – mortb Sep 04 '14 at 09:21
0

Note: I've used the TPL instead of using Threads directly since I think that the TPL is a better solution. You can of course have specific requirements which can mean that Threads is the better solution for your case.

Use a BlockingCollection<T> and fill the collection with the folder numbers. Each task handles an item of the collection, and the collection itself handles the multi-threading aspect so that each item is only handled by one consumer.

// Define the blocking collection with a maximum size of 15.
const int maxSize = 15;
var data = new BlockingCollection<int>(maxSize);

// Add the data to the collection.
// Do this in a separate task since BlockingCollection<T>.Add()
// blocks when the specified capacity is reached.
var addingTask = new Task(() => {
    for (int i = 1; i <= 20; i++) {
        data.Add(i);
    }
).Start();

// Define a signal-to-stop bool
var stop = false;

// Create 15 handle tasks.
// You can change this to threads if necessary, but the general idea is that
// each consumer continues to consume until the stop-boolean is set.
// The Take method returns only when an item is/becomes available.
for (int t = 0; t < maxSize; t++) {
    new Task(() => {
        while (!stop) {
            int item = data.Take();
            // Note: the Take method will block until an item comes available.
            HandleThisItem(item);
        }
    }).Start();
};

// Wait until you need to stop. When you do, set stop true
stop = true;
Community
  • 1
  • 1
Maarten
  • 22,527
  • 3
  • 47
  • 68