Bonjour,
j'essaie de créer une sorte de ThreadPool avec des Tasks.
J'ai une liste de tâches à effectuer représentées dans mon exemple ci-dessous par des classes WorkItem.
Certaines sont dépendantes d'autres, c'est à dire, qu'elles ne doivent être lancées que lorsque celles dont elle dépend sont terminées (cf la propriété Precedents).
J'ai donc créé des tâches qui sont lancées de suite et d'autres via Task.Factory.ContinueWhenAll.
Mon soucis est qu'avec ce code, je ne peux pas limiter le nombre de Tasks lancées en même temps, il faudrait pouvoir le limiter car si j'ai trop de tâches en parallèle, j'ai les performances qui chutent drastiquement.
J'ai tenté d'utiliser du PLinq et faire du travail du type .AsParallel().ForAll(() => ...) mais ça ne répond pas au besoin car il faut hiérarchiser les WorkItem via un rang et certains WorkItem ne se lancent pas alors que ces tâches précédentes sont terminées (je peux poster un code pour donner un exemple de cette solution et expliquer plus précisément ça ne fonctionne pas si cela s'avère nécessaire).
Je n'arrive pas à trouver de ressource sur le net, alors je me permets de vous demander votre avis.
Merci par avance pour votre aide.
Voici un exemple de code :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace PoolThread { class Program { static void Main(string[] args) { var travaux = new List<WorkItem>(); for (int i = 0; i < 10; i++) travaux.Add(new WorkItem(i * 1000, true)); for (int i = 0; i < 10; i++) travaux.Add(new WorkItem(i * 1000, true, travaux.ToArray())); var taches = new List<Task>(); foreach (var travail in travaux) { if (travail.Precedents.Count == 0) travail.Tache = new Task(() => travail.Work(), TaskCreationOptions.LongRunning); else travail.Tache = Task.Factory.ContinueWhenAll(travail.Precedents.Select(t => t.Tache).ToArray(), tasks => travail.Work(), TaskContinuationOptions.LongRunning); taches.Add(travail.Tache); } try { foreach (var travail in travaux) if (travail.Precedents.Count == 0) travail.Tache.Start(); Task.WaitAll(taches.ToArray()); Console.WriteLine("Fini"); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.ReadLine(); } } public class WorkItem { private static int _Increment = 0; private readonly int _No; private readonly int _Duree; private readonly bool _IsSuccess; public WorkItem(int duree, bool isSuccess, params WorkItem[] precedents) { _No = _Increment++; _Duree = duree; _IsSuccess = isSuccess; Precedents = new List<WorkItem>(precedents); } public bool Work() { Console.WriteLine($"Début {_No}"); Thread.Sleep(_Duree); Console.WriteLine($"Fin {_No}"); return _IsSuccess; } public List<WorkItem> Precedents { get; } public Task Tache { get; set; } } }
Partager