Concurrence

Rappels

Un cœur est une unité de calcul physique dans un processeur. Il exécute un ou plusieurs fil d’exécution (threads). Un processeur peut avoir plusieurs cœurs physiques, ce qui permet du parallélisme.

Threads

Création de threads

La création de threads s’effectue en utilisant le namespace System.Threading :

using System.Threading

Cela peut se créer selon deux méthodes :

  • ThreadStart : méthode sans paramètre
  • ParameterizedThreadStart : méthode avec un paramètre objet

Un nouveau thread ne pourra pas se lancer sans qu’une instruction Start() soit appelée.

using System.Threading

// Création et lancement de deux threads
var t1 = new Thread(RunLoop);
var t2 = new Thread(RunLoop);

t1.Start();
t2.Start();

void RunLoop() {
	for (var i = 1 ; i <= 10 ; i++) {
		Console.WriteLine(i);
	}
}

Par défaut, un thread est en avant-plan (foreground). Cela empêche l’arrêt du programme tant qu’il est actif. Pour qu’il bascule en arrière-plan, il faut utiliser l’instruction suivante :

var t1 = new Thread(RunLoop) {
	IsBackground = true;
};

Tâches

Création de tâches

using System
using System.Threading.Tasks;

var t1 = Task.Run(PrintLoop);
var t2 = Task.Run(PrintLoop);

await Task.WhenAll(t1, t2) // Créé une tâche qui se termine lorsque t1 et t2 se sont terminés

void PrintLoop()
{
	$Instruction
}

Une tâche doit être mise en attente quelque part dans le programme avec await pour éviter que le programme ne se coupe avant qu’elle ait le temps de s’exécuter complétement.


Concurrence structurée (parallels)

La classe Parallel possède des méthodes permettant de s’exécuter concomitamment dans le cadre de collections ou tableaux. Elle n’accepte que les int en paramètres.

using System;
using System.Threading.Tasks;

Parallele.For(1, 10, Print);

void Print(int i)
{
	Console.WriteLine($"This is loop #{i}");
}

Parallel va exécuter des itérations en parallèle, potentiellement sur des threads différents. L’ordre d’exécution est alors non déterministe.


Canaux (channels)