I am using following example .
using System;
using System.Threading;
public class MyThread
{
public void Thread1()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Hello world " + i);
Thread.Sleep(1000);
}
}
}
public class MyClass
{
public static void Main()
{
Console.WriteLine("Before start thread");
MyThread thr1 = new MyThread();
MyThread thr2 = new MyThread();
Thread tid1 = new Thread(new ThreadStart(thr1.Thread1) );
Thread tid2 = new Thread(new ThreadStart(thr2.Thread1) );
tid1.Start();
tid2.Start();
}
}
It works like this.
output :
Before start thread
Hello world 0
Hello world 0
Hello world 1
Hello world 1
Hello world 2
Hello world 2
Hello world 3
Hello world 3
Hello world 4
Hello world 4
Hello world 5
Hello world 5
Hello world 6
Hello world 6
Hello world 7
Hello world 7
Hello world 8
Hello world 8
Hello world 9
Hello world 9
It print i from first for loop and sleep for 1 sec move to second for loop.It prints i from second for loop sleep for 1 sec and move to first. I don't want it to context switch after every i print.I want like this after certain time after printing some value of i,sleep for some time within that period print value of i from second loop.After that expire again move back to first loop.
Ex: It suppose to print from 1 to 2-10 from first for loop and sleep move to second,it may print 1 to 2-10 from second for loop.and move to first loop.Value of i from from first loop may not be same for second.
Do you mean something like this?
class Program
{
static void Main(string[] args)
{
Task.WaitAll
(
Task.Run(() => new Work().DoWork(1)),
Task.Run(() => new Work().DoWork(2))
);
Console.ReadLine();
}
public class Work
{
public void DoWork(int taskNumber)
{
for(int i=0; i < 100; i++)
{
Console.WriteLine("Task {0} Value {1}", taskNumber, i);
}
}
}
}
so you get the following output
Task 1 Value 0
Task 1 Value 1
Task 1 Value 2
Task 1 Value 3
Task 1 Value 4
Task 1 Value 5
Task 1 Value 6
Task 1 Value 7
Task 1 Value 8
Task 1 Value 9
Task 1 Value 10
Task 1 Value 11
Task 1 Value 12
Task 2 Value 0
Task 2 Value 1
Task 2 Value 2
Task 2 Value 3
Task 2 Value 4
Task 2 Value 5
Task 2 Value 6
Task 2 Value 7
Task 2 Value 8
Task 2 Value 9
Task 2 Value 10
Task 2 Value 11
Task 2 Value 12
Task 2 Value 13
Task 2 Value 14
Task 2 Value 15
Task 2 Value 16
Task 2 Value 17
Task 2 Value 18
Task 2 Value 19
Task 2 Value 20
Task 2 Value 21
Task 2 Value 22
Task 2 Value 23
Task 2 Value 24
Task 2 Value 25
Task 2 Value 26
Task 2 Value 27
Task 2 Value 28
Task 2 Value 29
Task 2 Value 30
Task 2 Value 31
Task 2 Value 32
Task 2 Value 33
Task 2 Value 34
Task 2 Value 35
Task 2 Value 36
Task 1 Value 13
Task 1 Value 14
Task 1 Value 15
Task 1 Value 16
Task 1 Value 17
Task 1 Value 18
Task 1 Value 19
Task 1 Value 20
Task 1 Value 21
Task 1 Value 22
Task 1 Value 23
Task 1 Value 24
Task 1 Value 25
Task 1 Value 26
Task 1 Value 27
Task 1 Value 28
Task 1 Value 29
Task 1 Value 30
Task 1 Value 31
Task 1 Value 32
Task 1 Value 33
Task 2 Value 37
Task 2 Value 38
Task 2 Value 39
Task 2 Value 40
Task 2 Value 41
Task 2 Value 42
Task 2 Value 43
Task 2 Value 44
Task 2 Value 45
Task 2 Value 46
Task 2 Value 47
Task 2 Value 48
Task 2 Value 49
Task 2 Value 50
Task 2 Value 51
Task 2 Value 52
Task 2 Value 53
Task 2 Value 54
Task 2 Value 55
Task 1 Value 34
Task 1 Value 35
Task 1 Value 36
Task 1 Value 37
Task 1 Value 38
Task 1 Value 39
Task 1 Value 40
Task 1 Value 41
Task 1 Value 42
Task 1 Value 43
Task 1 Value 44
Task 1 Value 45
Task 1 Value 46
Task 1 Value 47
Task 1 Value 48
Task 2 Value 56
Task 2 Value 57
Task 2 Value 58
Task 2 Value 59
Task 2 Value 60
Task 2 Value 61
Task 2 Value 62
Task 2 Value 63
Task 2 Value 64
Task 2 Value 65
Task 2 Value 66
Task 2 Value 67
Task 2 Value 68
Task 2 Value 69
Task 2 Value 70
Task 2 Value 71
Task 2 Value 72
Task 2 Value 73
Task 2 Value 74
Task 2 Value 75
Task 2 Value 76
Task 1 Value 49
Task 1 Value 50
Task 1 Value 51
Task 1 Value 52
Task 1 Value 53
Task 1 Value 54
Task 1 Value 55
Task 1 Value 56
Task 1 Value 57
Task 1 Value 58
Task 1 Value 59
Task 1 Value 60
Task 1 Value 61
Task 1 Value 62
Task 1 Value 63
Task 1 Value 64
Task 1 Value 65
Task 1 Value 66
Task 1 Value 67
Task 1 Value 68
Task 1 Value 69
Task 2 Value 77
Task 2 Value 78
Task 2 Value 79
Task 2 Value 80
Task 2 Value 81
Task 2 Value 82
Task 2 Value 83
Task 2 Value 84
Task 2 Value 85
Task 2 Value 86
Task 2 Value 87
Task 2 Value 88
Task 2 Value 89
Task 2 Value 90
Task 2 Value 91
Task 2 Value 92
Task 2 Value 93
Task 2 Value 94
Task 2 Value 95
Task 2 Value 96
Task 2 Value 97
Task 2 Value 98
Task 2 Value 99
Task 1 Value 70
Task 1 Value 71
Task 1 Value 72
Task 1 Value 73
Task 1 Value 74
Task 1 Value 75
Task 1 Value 76
Task 1 Value 77
Task 1 Value 78
Task 1 Value 79
Task 1 Value 80
Task 1 Value 81
Task 1 Value 82
Task 1 Value 83
Task 1 Value 84
Task 1 Value 85
Task 1 Value 86
Task 1 Value 87
Task 1 Value 88
Task 1 Value 89
Task 1 Value 90
Task 1 Value 91
Task 1 Value 92
Task 1 Value 93
Task 1 Value 94
Task 1 Value 95
Task 1 Value 96
Task 1 Value 97
Task 1 Value 98
Task 1 Value 99
You OS will give every "Task" time for execute, is the time over it will wait until he get time again. So in this period the Task is "sleeping".
Pls let me now if this work for you.
Perhaps try looking at using Microsoft's Reactive Framework. It is designed to do this kind of thing.
Try this code:
var source = Observable.Range(0, 10);
var interval = Observable.Interval(TimeSpan.FromSeconds(1.0));
var query =
Observable
.Merge(
source.Select(n => $"A{n}").Buffer(3),
source.Select(n => $"B{n}").Buffer(3))
.SelectMany(x => x)
.Zip(interval, (n, _) => n);
query.Subscribe(i => Console.WriteLine($"Hello world {i}"));
Here's the output:
Hello world A0
Hello world A1
Hello world A2
Hello world B0
Hello world B1
Hello world B2
Hello world A3
Hello world A4
Hello world A5
Hello world B3
Hello world B4
Hello world B5
Hello world A6
Hello world A7
Hello world A8
Hello world B6
Hello world B7
Hello world B8
Hello world A9
Hello world B9
Notice the groups of 3 lots of the "A" and "B" values?
Each line is output one second after the previous one. That can be changed by changing the TimeSpan in the Interval operator.
This all happens in background threads (from the thread pool) and it lets you do all sorts of interesting filtering, grouping, querying, composition, etc.
Just NuGet "System.Reactive" and add using System.Reactive.Linq; to your code.
Related
Please consider this scenario:
For some math calculations I should find a number in specific place in a sorted list. For example consider this list:
1 - 2 - 3 - ... 17 - 18 - 19 - 20
I should to find number placed in 25% of count (count / 4). In above series I should get 5. It is worth noting that we haven't round count number but it's not a problem.
Now consider this table:
Type Number
----------------------
1 10
1 11
1 12
1 13
2 22
2 23
2 24
2 25
2 26
2 27
2 28
3 39
3 38
3 37
3 36
3 35
3 34
3 33
3 32
4 41
4 43
4 42
4 44
4 45
4 47
4 46
4 48
4 49
4 50
4 51
Another point is I'm sure that in every Type I have at least 1000
numbers, so above data in just for example.
according to above data I want to get this result:
Type Number
----------------------
1 11
2 23
3 33
4 43
One way to achieve this result is to loop throw distinct Type and get list of number and then sort it and then calculate count of that list and divide it by 4, then round the result and get specific Number with the index has been gotten.
But the problem with this approach is it needs many connection to database (1 for each Type). Is there any better solution to get desired result with 1 connection and 1 query execution. thanks
Interesting puzzle. In Sql Server you could use something like the following query;
select a.*
from (
select *, row_number() over(partition by type order by number) as row_number
from table_name
) a
join (
select type, count(*) as count
from table_name
group by type
) b on a.type = b.type
where a.row_number = b.count/4
(With whatever rounding you want for when count%4 != 0)
But I can't think how you would build that as a linq expression.
var percent = 0.25;
var val = res.GroupBy(x => x.type)
.ToDictionary(x => x.Key, x => x.OrderBy(y=>y).ToList());
var valuesTobeTaken = val.Select(x => new
{
x.Key,
index = ((int)Math.Round(x.Value.Count * percent))-1
});
Edge cases are not handled and the code is not too much optimized. You can work on that i guess
foreach (var rec in valuesTobeTaken)
{
Console.WriteLine(val[rec.Key][rec.index]);
}
I'm working on an inventory system for a game.
If the player inventory is empty or has less than 24 items, I want show 36 slots.
If the inventory has 24 or more items, I want to find the next number divisible by 12 and use that. Basically I always want to allow at least 12 extra slots, with a minimum of 36 total.
Here's the code I've tried which is not giving me desired results:
int testInventoryCount = 29;
int itemSlotCount = 36;
int itemSlotCount2 = 36;
int itemSlotCount3 = 36;
if (testInventoryCount >= 24)
{
itemSlotCount = ((testInventoryCount / 12) + 1) * 12;
itemSlotCount2 = (testInventoryCount + 12) - (testInventoryCount % 12);
itemSlotCount3 = (testInventoryCount + 12 / 2) / 12 * 12;
}
Debug.Log(testInventoryCount);
Debug.Log(itemSlotCount);
Debug.Log(itemSlotCount2);
Debug.Log(itemSlotCount3);
None of them are giving me the correct value.
For example, this is what I want:
If the inventory has 0 items, have 36 slots.
If the inventory has 20 items, have 36 slots.
If the inventory has 26 items, have 48 slots.
If the inventory has 30 items, have 48 slots.
If the inventory has 34 items, have 48 slots.
If the inventory has 60 items, have 72 slots.
If the inventory has 66 items, have 84 slots.
Etc...
I'm terrible at math. Halp.
I wrote a simple function for getting the number of necessary slots.
public static int get_slot_count(int item_count)
{
return Math.Max(36,(item_count / 12 + 2) * 12);
}
I tested and get the following results.
0 items / 36 slots
1 items / 36 slots
2 items / 36 slots
3 items / 36 slots
4 items / 36 slots
5 items / 36 slots
6 items / 36 slots
7 items / 36 slots
8 items / 36 slots
9 items / 36 slots
10 items / 36 slots
11 items / 36 slots
12 items / 36 slots
13 items / 36 slots
14 items / 36 slots
15 items / 36 slots
16 items / 36 slots
17 items / 36 slots
18 items / 36 slots
19 items / 36 slots
20 items / 36 slots
21 items / 36 slots
22 items / 36 slots
23 items / 36 slots
24 items / 48 slots
25 items / 48 slots
26 items / 48 slots
27 items / 48 slots
28 items / 48 slots
29 items / 48 slots
30 items / 48 slots
31 items / 48 slots
32 items / 48 slots
33 items / 48 slots
34 items / 48 slots
35 items / 48 slots
36 items / 60 slots
37 items / 60 slots
38 items / 60 slots
39 items / 60 slots
40 items / 60 slots
41 items / 60 slots
42 items / 60 slots
43 items / 60 slots
44 items / 60 slots
45 items / 60 slots
46 items / 60 slots
47 items / 60 slots
48 items / 72 slots
49 items / 72 slots
I am curious why you need more than 36 slots for 24 items. If you just need extra 12 slots, the following would be better and gives more reasonable results.
public static int get_slot_count(int item_count)
{
return Math.Max(36,((item_count - 1) / 12 + 2) * 12);
}
Test results.
0 items / 36 slots
1 items / 36 slots
2 items / 36 slots
3 items / 36 slots
4 items / 36 slots
5 items / 36 slots
6 items / 36 slots
7 items / 36 slots
8 items / 36 slots
9 items / 36 slots
10 items / 36 slots
11 items / 36 slots
12 items / 36 slots
13 items / 36 slots
14 items / 36 slots
15 items / 36 slots
16 items / 36 slots
17 items / 36 slots
18 items / 36 slots
19 items / 36 slots
20 items / 36 slots
21 items / 36 slots
22 items / 36 slots
23 items / 36 slots
24 items / 36 slots
25 items / 48 slots
26 items / 48 slots
27 items / 48 slots
28 items / 48 slots
29 items / 48 slots
30 items / 48 slots
31 items / 48 slots
32 items / 48 slots
33 items / 48 slots
34 items / 48 slots
35 items / 48 slots
36 items / 48 slots
37 items / 60 slots
38 items / 60 slots
39 items / 60 slots
40 items / 60 slots
41 items / 60 slots
42 items / 60 slots
43 items / 60 slots
44 items / 60 slots
45 items / 60 slots
46 items / 60 slots
47 items / 60 slots
48 items / 60 slots
49 items / 72 slots
Title may not explain fully what I want to do, so I made an image.
You can see there are 4 1D arrays(red numbers, black colored numbers are indexes), each of this array goes from 0 to 63. I want to somehow translate them, that for example, index 16 will point to first index of second array.
What I was thinking of, is a function where I give List of arrays and index that I want to get as input, and its returns me the index of array and exact index in this array as output.
I would like to have some hints or suggestions on how to proceed here to achieve this functionality.
Ok, your image shows an interleaved data of 16 elements, so you want to have (showing an example of only two matrices because of space :D)
Global index
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
-----------------------------------------------------------------------------------------------------
Array0 indexes - Array1 indexes
0 1 2 3 4 5 6 7 8 9 A B C D E F - 0 1 2 3 4 5 6 7 8 9 A B C D E F
-------------------------------------------------------------------------------------------------
Global index
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
-----------------------------------------------------------------------------------------------------
Array0 indexes - Array1 indexes
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F - 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
To get it you can do something like this:
public class CompositeIndex
{
public int ArrayNumber { get; set; }
public int ElementNumber { get; set; }
}
public static CompositeIndex GetIndex(int GlobalIndex, int ArrayCount, int ElementsToInterleave)
{
CompositeIndex index = new CompositeIndex();
int fullArrays = GlobalIndex / ElementsToInterleave; //In your example: 16 / 16 = 1;
index.ArrayNumber = fullArrays % ArrayCount; //In your example: 1 mod 4 = 1;
index.ElementNumber = GlobalIndex - (fullArrays * ElementsToInterleave); //In your example: 16 - (1 * 16) = 0;
return index;
}
Then, if you have 4 matrices and want to get the "global" index 16 you do:
var index = GetIndex(16, 4, 16);
This function allows you to use an indeterminated number of arrays and interleaved elements.
BTW, another time ask better your question, a lot more people will help you if they don't have to solve a puzzles to understand what you want...
i have this text file below:
001 Bulbasaur 45 49 49 65 65 45 Grass Poison
002 Ivysaur 60 62 63 80 80 60 Grass Poison
003 Venusaur 80 82 83 100 100 80 Grass Poison
004 Charmander 39 52 43 60 50 65 Fire
005 Charmeleon 58 64 58 80 65 80 Fire
I have written this piece of code to split it into lines then into variables but it refuses to work, my apology's if i am asking this in the wrong place. (unity C# question).
var lines = textFile.text.Split("\n"[0]);
allMonsters = new Monsters[lines.Length];
List<string> lineSplit = new List<string>();
for (int i = 0; i < lines.Length; i++) {
Debug.Log(lines[i]);
lineSplit.Clear();
lineSplit = lines[i].Split(' ').ToList ();
int ID = int.Parse(lineSplit[0]);
string Name = lineSplit[1].ToString();
float HP = float.Parse(lineSplit[2]);
float ATK = float.Parse(lineSplit[3]);
float DEF = float.Parse(lineSplit[4]);
float SPATK = float.Parse(lineSplit[5]);
float SpDEF = float.Parse(lineSplit[6]);
float speed = float.Parse(lineSplit[7]);
FirstType Ft = (FirstType)System.Enum.Parse(typeof(FirstType),lineSplit[8]);
SecondType ST = (SecondType)System.Enum.Parse(typeof(SecondType),lineSplit[9]); }
The code works for the first line but then on the second run of this code i get null reference to an object error, please help me.
Note, variables are assigned to so they aren't overwritten after code.
EDIT: LineSplit variable is over 1200 elements long, so i do not think unity is clearing the array properly could this be the issue?
I'm not sure about the second iteration, but on the 4th iteration line 004 Charmander 39 52 43 60 50 65 Fire have only 9 parameters (by split of space) and you using lineSplit[9], so there you will get NullPointerException.
When working with text files, linefeed often comes along with carriage return.
Try
var lines = textFile.text.Split(new string[]{"\r\n"}, System.StringSplitOptions.None);
in the first line.
My scenario:
I need to process a list of elements. Each element processing is highly time consuming (1-10 seconds)
Instead of a
List retval = new List();
foreach (item in myList)
retval.Add(ProcessItem(item));
return retval;
I want to parallel process each item.
I know .NET has got a number of approach for parallel processing: what is the best one? (note, I'm stuck to 3.5 framework version, cannot use Task, async and all nancy features coming with .Net 4...)
Here my try using delegates:
private void DoTest(int processingTaskDuration)
{
List<int> itemsToProcess = new List<int>();
for (int i = 1; i <= 20; i++)
itemsToProcess.Add(i);
TestClass tc = new TestClass(processingTaskDuration);
DateTime start = DateTime.Now;
List<int> result = tc.ProcessList(itemsToProcess);
TimeSpan elapsed = DateTime.Now - start;
System.Diagnostics.Debug.WriteLine(string.Format("elapsed (msec)= {0}", (int)elapsed.TotalMilliseconds));
}
public class TestClass
{
static int s_Counter = 0;
static object s_lockObject = new Object();
int m_TaskMsecDuration = 0;
public TestClass() :
this(5000)
{
}
public TestClass(int taskMsecDuration)
{
m_TaskMsecDuration = taskMsecDuration;
}
public int LongOperation(int itemToProcess)
{
int currentCounter = 0;
lock (s_lockObject)
{
s_Counter++;
currentCounter = s_Counter;
}
System.Diagnostics.Debug.WriteLine(string.Format("LongOperation\tStart\t{0}\t{1}\t{2}", currentCounter, System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("HH:mm:ss.ffffff")));
// time consuming task, e.g 5 seconds
Thread.Sleep(m_TaskMsecDuration);
int retval = itemToProcess * 2;
System.Diagnostics.Debug.WriteLine(string.Format("LongOperation\tEnd \t{0}\t{1}\t{2}", currentCounter, System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("HH:mm:ss.ffffff")));
return retval;
}
delegate int LongOperationDelegate(int itemToProcess);
public List<int> ProcessList(List<int> itemsToProcess)
{
List<IAsyncResult> asyncResults = new List<IAsyncResult>();
LongOperationDelegate del = LongOperation;
foreach (int item in itemsToProcess)
{
IAsyncResult res = del.BeginInvoke(item, null, null);
asyncResults.Add(res);
}
// list of waitHandles to wait for
List<WaitHandle> waitHandles = new List<WaitHandle>();
asyncResults.ForEach(el => waitHandles.Add(el.AsyncWaitHandle));
// wait for processing every item
WaitHandle.WaitAll(waitHandles.ToArray());
// retrieve result of processing
List<int> retval = new List<int>();
asyncResults.ForEach(res =>
{
int singleProcessingResult = del.EndInvoke(res);
retval.Add(singleProcessingResult);
}
);
return retval;
}
}
And thats some output (column #3 is a progressive counter, use it to match start with end of a call, #4 is threadID and last is a timeStamp)
LongOperation Start 1 6 15:11:18.331619
LongOperation Start 2 12 15:11:18.331619
LongOperation Start 3 13 15:11:19.363722
LongOperation Start 4 14 15:11:19.895775
LongOperation Start 5 15 15:11:20.406826
LongOperation Start 6 16 15:11:21.407926
LongOperation Start 7 17 15:11:22.410026
LongOperation End 1 6 15:11:23.360121
LongOperation End 2 12 15:11:23.361122
LongOperation Start 8 12 15:11:23.363122
LongOperation Start 9 6 15:11:23.365122
LongOperation Start 10 18 15:11:23.907176
LongOperation End 3 13 15:11:24.365222
LongOperation Start 11 13 15:11:24.366222
LongOperation End 4 14 15:11:24.897275
LongOperation Start 12 14 15:11:24.898275
LongOperation Start 13 19 15:11:25.407326
LongOperation End 5 15 15:11:25.408326
LongOperation Start 14 15 15:11:25.412327
LongOperation Start 15 20 15:11:26.407426
LongOperation End 6 16 15:11:26.410426
LongOperation Start 16 16 15:11:26.410426
LongOperation Start 17 21 15:11:27.408526
LongOperation End 7 17 15:11:27.411527
LongOperation Start 18 17 15:11:27.413527
LongOperation End 8 12 15:11:28.365622
LongOperation Start 19 12 15:11:28.366622
LongOperation End 9 6 15:11:28.366622
LongOperation Start 20 6 15:11:28.389624
LongOperation End 10 18 15:11:28.908676
LongOperation End 11 13 15:11:29.367722
LongOperation End 12 14 15:11:29.899775
LongOperation End 13 19 15:11:30.411827
LongOperation End 14 15 15:11:30.413827
LongOperation End 15 20 15:11:31.407926
LongOperation End 16 16 15:11:31.411927
LongOperation End 17 21 15:11:32.413027
LongOperation End 18 17 15:11:32.416027
LongOperation End 19 12 15:11:33.389124
LongOperation End 20 6 15:11:33.391124
elapsed (msec)= 15075
So:
Is Delegate approach the right one?
Did I implement it right?
If so, why the 3rd operations starts one second after the first two (and so on)?
I mean, I'd like the whole processing complete in more or less the time of one single processing, but it seems the system uses thread pool in a strange way. After all, I'm asking 20 threads, and it waits to span the 3rd one just after the first two calls.
I think the 3.5 backport of Reactive Extensions comes with an implementation of Parallel.ForEach() that you should be able to use. The port should just contain only what was needed to get Rx to work on 3.5, but that should be enough.
Others have tried implementing it as well, basically just queuing work items on ThreadPool.
void Main()
{
var list = new List<int>{ 1,2,3 };
var processes = list.Count();
foreach (var item in list)
{
ThreadPool.QueueUserWorkItem(s => {
ProcessItem(item);
processes--;
});
}
while (processes > 0) { Thread.Sleep(10); }
}
static void ProcessItem(int item)
{
Thread.Sleep(100); // do work
}
I got rid of my third question:
If so, why the 3rd operations starts one second after the first two
(and so on)?
The problem seems to be in the default way ThreadPool manages thread spawning: see http://msdn.microsoft.com/en-us/library/0ka9477y%28v=VS.90%29.aspx. Quote:
The thread pool has a built-in delay (half a second in the .NET
Framework version 2.0) before starting new idle threads. If your
application periodically starts many tasks in a short time, a small
increase in the number of idle threads can produce a significant
increase in throughput. Setting the number of idle threads too high
consumes system resources needlessly.
It seems a call to ThreadPool.SetMinThreads with a proper value helps a lot.
At the start of my ProcessList, I inserted a call to this method:
private void SetUpThreadPool(int numThreadDesired)
{
int currentWorkerThreads;
int currentCompletionPortThreads;
ThreadPool.GetMinThreads(out currentWorkerThreads, out currentCompletionPortThreads);
//System.Diagnostics.Debug.WriteLine(string.Format("ThreadPool.GetMinThreads: workerThreads = {0}, completionPortThreads = {1}", workerThreads, completionPortThreads));
const int MAXIMUM_VALUE_FOR_SET_MIN_THREAD_PARAM = 20;
int numMinThreadToSet = Math.Min(numThreadDesired, MAXIMUM_VALUE_FOR_SET_MIN_THREAD_PARAM);
if (currentWorkerThreads < numMinThreadToSet)
ThreadPool.SetMinThreads(numThreadDesired, currentCompletionPortThreads);
}
public List<int> ProcessList(List<int> itemsToProcess)
{
SetUpThreadPool(documentNumberList.Count);
...
}
Now all thread (up to 20) start at the same moment, without delay. I think 20 is a good compromise for MAXIMUM_VALUE_FOR_SET_MIN_THREAD_PARAM: not too hight, and fits my particular requirements
Still wondering about main questions
Is Delegate approach the right one?
Did I implement it right?
Thanks to everyone helping.