La vie

Comment utiliser le multi-threading avec des tâches en C #

Comment utiliser le multi-threading avec des tâches en C #

Le terme de programmation informatique "thread" est l'abréviation de thread d'exécution, dans lequel un processeur suit un chemin spécifié dans votre code. Le concept de suivre plus d'un thread à la fois introduit le sujet du multi-tâches et du multi-threading.

Une application contient un ou plusieurs processus. Pensez à un processus comme à un programme exécuté sur votre ordinateur. Maintenant, chaque processus a un ou plusieurs threads. Une application de jeu peut avoir un fil pour charger les ressources du disque, une autre pour faire de l'IA et une autre pour exécuter le jeu en tant que serveur.

Dans .NET / Windows, le système d'exploitation alloue du temps de processeur à un thread. Chaque thread garde une trace des gestionnaires d'exceptions et de la priorité d'exécution, et il a un emplacement pour enregistrer le contexte du thread jusqu'à son exécution. Le contexte de fil est l'information que le fil doit reprendre.

Multi-tâches avec des threads

Les threads prennent un peu de mémoire et leur création prend un peu de temps, donc vous ne voulez généralement pas en utiliser beaucoup. N'oubliez pas qu'ils se font concurrence pour le temps processeur. Si votre ordinateur dispose de plusieurs processeurs, Windows ou .NET peut exécuter chaque thread sur un processeur différent, mais si plusieurs threads s'exécutent sur le même processeur, un seul peut être actif à la fois et le changement de threads prend du temps.

La CPU exécute un thread pour quelques millions d'instructions, puis passe à un autre thread. Tous les registres de la CPU, le point d'exécution du programme actuel et la pile doivent être sauvegardés quelque part pour le premier thread, puis restaurés ailleurs pour le prochain thread.

Créer un fil

Dans le système de noms. Threading, vous trouverez le type de fil. Le thread constructeur (ThreadStart) crée une instance d'un thread. Cependant, dans le code C # récent, il est plus probable de passer une expression lambda qui appelle la méthode avec des paramètres quelconques.

Si vous n'êtes pas sûr des expressions lambda, consultez LINQ.

Voici un exemple de fil créé et démarré:

en utilisant le système;

using System.Threading;
espace de noms ex1
{
programme de classe
{
public statique vide Write1 ()
{
Console.Write ('1');
Thread.Sleep (500);
}
static void Main (string args)
{
tâche var = nouveau thread (Write1);
task.Start ();
pour (var i = 0; i <10; i ++)
{
Console.Write ('0');
Console.Write (task.IsAlive? 'A': 'D');
Thread.Sleep (150);
}
Console.ReadKey ();
}
}
}

Tout cet exemple fait est d'écrire "1" sur la console. Le thread principal écrit 10 fois un "0" sur la console, suivi à chaque fois d'un "A" ou d'un "D" selon que l'autre thread est toujours actif ou mort.

L'autre thread ne s'exécute qu'une fois et écrit un "1". Après le délai d'une demi-seconde dans le thread Write1 (), le thread se termine et la tâche.IsAlive dans la boucle principale renvoie désormais "D".

Pool de threads et bibliothèque parallèle de tâches

Au lieu de créer votre propre thread, utilisez un pool de threads, sauf si vous en avez vraiment besoin. À partir de .NET 4.0, nous avons accès à la bibliothèque de tâches parallèle (TPL). Comme dans l'exemple précédent, nous avons encore besoin d'un peu de LINQ, et oui, ce sont toutes des expressions lambda.

Les tâches utilisent le pool de threads en arrière-plan, mais optimisent leur utilisation en fonction du nombre utilisé.

L'objet principal de la TPL est une tâche. C'est une classe qui représente une opération asynchrone. Le moyen le plus courant de lancer l'exécution consiste à utiliser Task.Factory.StartNew comme suit:

Task.Factory.StartNew (() => DoQuelquechose ());

Où DoSomething () est la méthode qui est exécutée. Il est possible de créer une tâche et de ne pas la lancer immédiatement. Dans ce cas, utilisez simplement Task comme ceci:

var t = new Task (() => Console.WriteLine ("Hello"));

t.Start ();

Cela ne démarre pas le fil tant que le .Start () n’est pas appelé. Dans l'exemple ci-dessous, il y a cinq tâches.

en utilisant le système;
using System.Threading;
using System.Threading.Tasks;
espace de noms ex1
{
programme de classe
{
public statique vide Write1 (int i)
{
Console.Write (i);
Thread.Sleep (50);
}
static void Main (string args)
{
pour (var i = 0; i <5; i ++)
{
valeur var = i;
var runningTask = Task.Factory.StartNew (() => Write1 (valeur));
}
Console.ReadKey ();
}
}
}

Exécutez-le et vous obtiendrez les chiffres de 0 à 4 dans un ordre aléatoire, tel que 03214. En effet, l'ordre d'exécution des tâches est déterminé par .NET.

Vous vous demandez peut-être pourquoi la valeur var = i est nécessaire. Essayez de l'enlever et d'appeler Write (i), et vous verrez quelque chose d'inattendu comme 55555. Pourquoi? C'est parce que la tâche affiche la valeur de i au moment de son exécution, et non à sa création. En créant une nouvelle variable à chaque fois dans la boucle, chacune des cinq valeurs est correctement stockée et sélectionnée.


Video, Sitemap-Video, Sitemap-Videos