Ottima domanda. Nel tuo esempio, il livello di parallelizzazione è piuttosto basso anche su un processore quad core, ma con un po 'di attesa il livello di parallelizzazione può diventare piuttosto alto.
// Max concurrency: 5
[Test]
public void Memory_Operations()
{
ConcurrentBag<int> monitor = new ConcurrentBag<int>();
ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
var arrayStrings = new string[1000];
Parallel.ForEach<string>(arrayStrings, someString =>
{
monitor.Add(monitor.Count);
monitor.TryTake(out int result);
monitorOut.Add(result);
});
Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}
Ora guarda cosa succede quando viene aggiunta un'operazione di attesa per simulare una richiesta HTTP.
// Max concurrency: 34
[Test]
public void Waiting_Operations()
{
ConcurrentBag<int> monitor = new ConcurrentBag<int>();
ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
var arrayStrings = new string[1000];
Parallel.ForEach<string>(arrayStrings, someString =>
{
monitor.Add(monitor.Count);
System.Threading.Thread.Sleep(1000);
monitor.TryTake(out int result);
monitorOut.Add(result);
});
Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}
Non ho ancora apportato alcuna modifica e il livello di concorrenza/parallelizzazione è aumentato drammaticamente. La concorrenza può aumentare il suo limite con ParallelOptions.MaxDegreeOfParallelism
.
// Max concurrency: 43
[Test]
public void Test()
{
ConcurrentBag<int> monitor = new ConcurrentBag<int>();
ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
var arrayStrings = new string[1000];
var options = new ParallelOptions {MaxDegreeOfParallelism = int.MaxValue};
Parallel.ForEach<string>(arrayStrings, options, someString =>
{
monitor.Add(monitor.Count);
System.Threading.Thread.Sleep(1000);
monitor.TryTake(out int result);
monitorOut.Add(result);
});
Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}
// Max concurrency: 391
[Test]
public void Test()
{
ConcurrentBag<int> monitor = new ConcurrentBag<int>();
ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
var arrayStrings = new string[1000];
var options = new ParallelOptions {MaxDegreeOfParallelism = int.MaxValue};
Parallel.ForEach<string>(arrayStrings, options, someString =>
{
monitor.Add(monitor.Count);
System.Threading.Thread.Sleep(100000);
monitor.TryTake(out int result);
monitorOut.Add(result);
});
Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}
Si consiglia di impostare ParallelOptions.MaxDegreeOfParallelism
. Non aumenterà necessariamente il numero di thread in uso, ma ti garantirà solo l'avvio di un numero ragionevole di thread, che sembra essere la tua preoccupazione.
Infine, per rispondere alla domanda, non è possibile avviare tutte le discussioni contemporaneamente. Usa Parallel.Invoke se stai cercando di invocare in parallelo perfettamente ad es. testare le condizioni della gara.
// 636462943623363344
// 636462943623363344
// 636462943623363344
// 636462943623363344
// 636462943623363344
// 636462943623368346
// 636462943623368346
// 636462943623373351
// 636462943623393364
// 636462943623393364
[Test]
public void Test()
{
ConcurrentBag<string> monitor = new ConcurrentBag<string>();
ConcurrentBag<string> monitorOut = new ConcurrentBag<string>();
var arrayStrings = new string[1000];
var options = new ParallelOptions {MaxDegreeOfParallelism = int.MaxValue};
Parallel.ForEach<string>(arrayStrings, options, someString =>
{
monitor.Add(DateTime.UtcNow.Ticks.ToString());
monitor.TryTake(out string result);
monitorOut.Add(result);
});
var startTimes = monitorOut.OrderBy(x => x.ToString()).ToList();
Console.WriteLine(string.Join(Environment.NewLine, startTimes.Take(10)));
}
stavo usando Parallel.ForEach (FilePathArray, path => ... da leggere circa 24.000 file stasera la creazione di un nuovo file per ogni file che ho letto in. Codice molto semplice. Sembra che anche i 6 discussioni era sufficiente per sopraffare il disco da 7200 RPM di cui stavo leggendo al 100% di utilizzo.Per il periodo di poche ore ho visto la libreria parallela girare oltre 8.000 thread.Ho provato usando MaxDegreeOfParallelism e sono sicuro che i thread 8000+ sono scomparsi. più volte ora con lo stesso risultato –
È possibile * avviare 1000 thread per alcuni degenerati "DoSomething". (Come nel caso in cui attualmente sto affrontando un problema nel codice di produzione che non è riuscito a impostare un limite e ha generato spa + 200 thread in tal modo spuntando il pool di connessioni SQL .. Raccomando di impostare il DOP massimo per qualsiasi lavoro non può essere banalmente ragionato in quanto esplicitamente legato alla CPU.) – user2864740