Bonjour
un controle appartient au thread principal et un thread secondaire n'a pas le droit de les modifier.
Imagine que tu sois en train d'écrire dans le datagridview et qu'en même temps le thread modifie la case que tu saisis, il va y avoir conflit.
D'autre part lancer un thread via un timer n'est pas judicieux.
Si ta base de données est tellement grande que la lecture dure plus de 2 secondes, que va t il se passer?
Il faut que le thread boucle sur lui même, et éventuellement gère son temps.
MsgBox(ex.Message)
n'est pas une instruction VB.Net, mais une tolérance de Microsoft d'importer certains codes VB6. Dans 99.99% des cas, cela fonctionne, mais quand il y a un bug il est difficile de trouver pourquoi. C'est pourquoi on conseille d'enlever l'import à VisualBasic de tout projet VB.net, voir ici. D'autre part MessageBox étant aussi un contrôle, il y aura peut être aussi une erreur cross thread.
L'utilité d'un BindingSource est de partager une source de données et d'en mettre en forme l'affichage.
Dim bs As New BindingSource
con.Open()
cmd.Connection = con
cmd.CommandType = CommandType.Text
cmd.CommandText = "select * from users where username like '%Jean%'"
da.SelectCommand = cmd
da.Fill(ds)
bs.DataSource = ds
DataGridView.DataSource = bs
Là tu crées un BindingSource uniquement à destination du DataGridView et tu ne fais aucune mise en forme.
Tu peux donc t'en passer.
con.Open()
cmd.Connection = con
cmd.CommandType = CommandType.Text
cmd.CommandText = "select * from users where username like '%Jean%'"
da.SelectCommand = cmd
da.Fill(ds)
DataGridView.DataSource = ds
ferait exactement pareil, hormis le problème de thread, tout en optimisant le temps de calcul.
Enfin, tu parles de temps réel et tu utilises un backgroundwork, qui comme son nom l'indique effectue une tache de fond, moins prioritaire.
Si tu as besoin d'un grande réactivité ça n'est peut être pas le thread le plus adapté. Par contre normalement, il permet de transmettre des données sans Invoke.
Essaye ceci, pas testé chez moi, je n'ai pas mysql.
Private Sub f1f58e8c06b2a61ce13e0c0aa9473a72()
AddHandler bgw.DoWork, AddressOf bgw_DoWork
bgw.WorkerReportsProgress = True 'autorise d'envoyer une progression, un rapport, un resultat intermédiaire
AddHandler bgw.ProgressChanged, AddressOf bgw_ProgressChanged 'abonement à la progression
AddHandler bgw.RunWorkerCompleted, AddressOf bgw_RunWorkerCompleted 'abonoment au signalement de la fin de progression
bgw.RunWorkerAsync( { "select * from users where username like '%Jean%'", "select * from users where username like '%Jean%'" }) 'lance le backgroundworker avec les infos de connection et de recherche en paramètre
End Sub
Private Sub bgw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
Try
Dim tableau() As String = CType(e.Argument, String ())
Dim con As New MySqlConnection(tableau(0))
Dim cmd As New MySqlCommand()
Dim da As New MySqlDataAdapter()
Dim ds As New DataTable()
Do
con.Open()
cmd.Connection = con
cmd.CommandType = CommandType.Text
cmd.CommandText = tableau(1)
da.SelectCommand = cmd
da.Fill(ds)
bgw.ReportProgress(0, da) 'j'envoie une progression à 0% et l'état de da à cet instant
con.Close()
Thread.Sleep(2000) 'je fais une pause de 2 secondes
Loop While True
Catch ex As Exception
e.Result = ex 'je place l'erreur en resultat du backgroundworker
End Try
End Sub
Private Sub bgw_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
Dim da As DataTable = TryCast(e.UserState, DataTable)
If da Is Nothing Then
Return ' l'objet UserState n'est pas un DataTable
End If
dataGridView1.DataSource = da
End Sub
Private Sub bgw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
Dim erreur As Exception = TryCast(e.Result, Exception)
If erreur Is Nothing Then
Return
End If
MessageBox.Show(erreur.Message)
End Sub
Ce backgroundworker ne s'arretra de lui même que s'il y a une erreur car j'ai mis Loop While True
.
Il est possible qu'il y ait encore des erreurs cross thread (si par exemple ce code est dans un autre projet que celui de la form).
Il faudra alors passer par de Invoke.