Bonjour,

Je viens de modifier cet exemple de synchronisation de threads :

Ouvrir une forme avec 3 boutons : Démarrer, Arrêter et Quitter et saisir ce 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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
Imports System.Threading
Imports System.Runtime.InteropServices
 
 
Public Class Form1
 
    <DllImport("user32.dll")>
    Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As Integer) As Boolean
    End Function 'pour positionner la fenêtre de pywin64.exe
    <DllImport("user32.dll")>
    Shared Function SetWindowText(ByVal hwnd As IntPtr, ByVal windowName As String) As Boolean
    End Function 'pour changer le titre de la fenêtre de pywin64.exe
 
    Private tTask1 As System.Threading.Thread
    Private tTask2 As System.Threading.Thread
    Private tTask3 As System.Threading.Thread
    Private tTask4 As System.Threading.Thread
 
    Private mreTask1 As System.Threading.ManualResetEvent
    Private mreTask2 As System.Threading.ManualResetEvent
    Private mreTask3 As System.Threading.ManualResetEvent
    Private mreTask4 As System.Threading.ManualResetEvent
 
    Private Delegate Sub dTask1()
 
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        StartAllTasks()
    End Sub
 
    ' toutes les applications fonctionnant sous ce thread sont des progressbar pour visulaiser l'effet
 
    Private Sub Task1()
        Do
            Me.BeginInvoke(New dTask1(AddressOf sTask1))
            System.Threading.Thread.Sleep(100)
        Loop Until ProgressBar1.Value >= ProgressBar1.Maximum
        mreTask1.Set()
    End Sub
    Private Sub sTask1()
        Me.ProgressBar1.PerformStep()
    End Sub
 
    Private Sub Task2()
        Do
            Me.BeginInvoke(New dTask1(AddressOf sTask2))
            System.Threading.Thread.Sleep(100)
        Loop Until ProgressBar2.Value >= ProgressBar2.Maximum
        mreTask2.Set()
    End Sub
    Private Sub sTask2()
        Me.ProgressBar2.PerformStep()
    End Sub
 
    Private Sub Task3()
        Do
            Me.BeginInvoke(New dTask1(AddressOf sTask3))
            System.Threading.Thread.Sleep(100)
        Loop Until ProgressBar3.Value >= ProgressBar3.Maximum
        mreTask3.Set()
    End Sub
    Private Sub sTask3()
        Me.ProgressBar3.PerformStep()
    End Sub
 
    Private Sub Task4()
        mreTask1.WaitOne()
        mreTask2.WaitOne()
        mreTask3.WaitOne()
        Do
            Me.BeginInvoke(New dTask1(AddressOf sTask4))
            System.Threading.Thread.Sleep(100)
        Loop Until ProgressBar4.Value >= ProgressBar4.Maximum
        mreTask4.Set()
 
        Do
        Loop Until tTask4.IsAlive = True
 System.Threading.Thread.Sleep(3000)
        Button3.PerformClick()
 
    End Sub
    Private Sub FinalTask()
        System.Threading.Thread.Sleep(3000)
        Close()
    End Sub
 
    Private Sub sTask4()
        Me.ProgressBar4.PerformStep()
 
    End Sub
 
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
 
        Me.Text = My.Application.Info.ProductName & " from " & My.Application.Info.CompanyName
        ProgressBar1.Maximum = 200
        ProgressBar2.Maximum = 100
        ProgressBar3.Maximum = 140
        ProgressBar4.Maximum = 240
 
        'cré  ManualResetEvent
        mreTask1 = New System.Threading.ManualResetEvent(False)
        mreTask2 = New System.Threading.ManualResetEvent(False)
        mreTask3 = New System.Threading.ManualResetEvent(False)
        mreTask4 = New System.Threading.ManualResetEvent(False)
 
    End Sub
 
    ' Démarre tous les Task au même moment
    Private Sub StartAllTasks()
        If tTask1 IsNot Nothing Then tTask1 = Nothing
        tTask1 = New System.Threading.Thread(AddressOf Task1)
        tTask1.IsBackground = True
        tTask1.Start()
 
        If tTask2 IsNot Nothing Then tTask2 = Nothing
        tTask2 = New System.Threading.Thread(AddressOf Task2)
        tTask2.IsBackground = True
        tTask2.Start()
 
        If tTask3 IsNot Nothing Then tTask3 = Nothing
        tTask3 = New System.Threading.Thread(AddressOf Task3)
        tTask3.IsBackground = True
        tTask3.Start()
 
        If tTask4 IsNot Nothing Then tTask4 = Nothing
        tTask4 = New System.Threading.Thread(AddressOf Task4)
        tTask4.IsBackground = True
        tTask4.Start()
 
    End Sub
 
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        tTask1.Abort()
    End Sub
 
    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        Close()
    End Sub
 
End Class
L'idée est de synchroniser 3 Progressbar, puis à la fin du process de démarrer une quatrième Progressbar.

Tout fonctionne jusqu'à la fin ou j'ai un retour d'erreur System.InvalidoperationException :
"Opération inter-threads non valide : le contrôle 'Button 3' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé."

Le problème ce produit losque s'exécute.

L'idée du Button3.PerfromClick() est d'arrêter au bout de 3 secondes le Form lorsque le Task4 est fini dans le code même si on oubli d'appuyer sur Quitter (Button3)

Voici le code en cause :

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
  Private Sub Task4()
        mreTask1.WaitOne()
        mreTask2.WaitOne()
        mreTask3.WaitOne()
        Do
            Me.BeginInvoke(New dTask1(AddressOf sTask4))
            System.Threading.Thread.Sleep(100)
        Loop Until ProgressBar4.Value >= ProgressBar4.Maximum
        mreTask4.Set()
 
        Do
        Loop Until tTask4.IsAlive = True
 System.Threading.Thread.Sleep(3000)
        Button3.PerformClick()
 
    End Sub
OK on ne peut pas faire de clôture du Form en inter-thread.

Comment faire pour que le Form se ferme au bout de 3 secondes après la fin de task 4 ?

En vous remerciant pour vos idées.

A+