Modifier un controle textB en threadsafe
Bonjour
j'essai de modifier un textbox ou un label à partir de thread, voici le code essayé
Code:
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
| Imports System.Threading
Imports System.IO
Imports System.Text
Imports System.Net.NetworkInformation
Public Class Form1
Delegate Sub OneArgSub(ByVal Msg As String)
Dim deleg As OneArgSub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Créer un nouveau thread et définir sont point de départ
Dim t As New Threading.Thread(New ThreadStart(AddressOf DotheTask))
Dim t1 As New Threading.Thread(New ThreadStart(AddressOf DotheTask))
Dim t2 As New Threading.Thread(New ThreadStart(AddressOf DotheTask))
'Exécute le nouveau thread
t.Start()
t1.Start()
t2.Start()
End Sub
Sub DotheTask()
Dim i As Integer
For i = 1 To 10
'Monte que le thread a reçu les bonnes valeurs.
'Console.WriteLine("Msg # {0} du thread principal avec la valeur", i.ToString)
deleg = New OneArgSub(AddressOf LblEnvok)
SyncLock deleg
deleg.Invoke("Msg # " & i & " du thread principal avec la valeur")
End SyncLock
Threading.Thread.Sleep(200)
Next
End Sub
Sub LblEnvok(ByVal msg As String)
Label1.Text = msg.ToString
End Sub
End Class |
et le message d'erreur suivant apparait
Citation:
L'exception System.InvalidOperationException n'a pas été gérée
Message=Opération inter-threads non valide*: le contrôle 'Label1' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.
Source=System.Windows.Forms
StackTrace:
à System.Windows.Forms.Control.get_Handle()
à System.Windows.Forms.Control.set_WindowText(String value)
à System.Windows.Forms.Control.set_Text(String value)
à System.Windows.Forms.Label.set_Text(String value)
à thread.Form1.LblEnvok(String msg) dans C:\Users\Mario\documents\visual studio 2010\Projects\thread1\thread1\Form1.vb:ligne 36
à thread.Form1.DotheTask() dans C:\Users\Mario\documents\visual studio 2010\Projects\thread1\thread1\Form1.vb:ligne 29
à System.Threading.ThreadHelper.ThreadStart_Context(Object state)
à System.Threading.ExecutionContext.runTryCode(Object userData)
à System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
à System.Threading.ThreadHelper.ThreadStart()
InnerException:
merci de votre aide
maj Affichage UI par Threads
bonjour
voici le schema qu'il y a lieu de retenir pour l'affichage sur l'UI.
Il implique le test de Control.InvokeRequired,l'appel Asynchrone Form.BeginInvoke du delegue Affichage et l'appel normal de la procedure d'Affichage à partir de Dotask.
Code:
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
|
Imports System.Threading
Imports System.IO
Imports System.Text
Imports System.Net.NetworkInformation
Public Class Form1
Delegate Sub UIOneArgSub(ByVal Msg As String)
Dim deleg As UIOneArgSub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Créer un nouveau thread et définir sont point de départ
Dim t As New Threading.Thread(New ThreadStart(AddressOf DotheTask))
Dim t1 As New Threading.Thread(New ThreadStart(AddressOf DotheTask))
Dim t2 As New Threading.Thread(New ThreadStart(AddressOf DotheTask))
'Exécute le nouveau thread
t.Start()
t1.Start()
t2.Start()
End Sub
Sub DotheTask()
Dim i As Integer
For i = 1 To 10
'Montre que le thread a reçu les bonnes valeurs.
'Console.WriteLine("Msg # {0} du thread principal avec la valeur", i.ToString)
'Appel normal de la proc d'affichage
LblEnvok("Msg # " & i & " du thread principal avec la valeur")
Threading.Thread.Sleep(200)
Next
End Sub
Sub LblEnvok(ByVal msg As String)
'Control.InvokeRequired = False <=>Appel normal du Form
If Not Label1.InvokeRequired Then
Label1.Text = msg.ToString
Else 'non Appel à delegue de Maniere Asynchrone (BeginInvoke)
deleg = New UIOneArgSub(AddressOf LblEnvok)
Me.BeginInvoke(deleg, New Object() {msg})
End If
End Sub
End Class |
BON CODE....