问题
I'm trying to load data from a SQL Server database into a DataGridView using threading with delegates and later will try to add a loading or waiting form. But I can't make it work.
Dim t1 As Thread
Private Delegate Sub delegate_updatedgv()
Private Sub mainform_Load(sender As Object, e As EventArgs) Handles MyBase.Load
t1 = New Thread(AddressOf load_dgv)
t1.Start()
End Sub
Private Function load_dgv()
Try
If DBCon.State = ConnectionState.Closed Then
DBCon.Open()
End If
DBCmd = New SqlCommand("SELECT * FROM Jobs ", DBCon)
DBCmd.ExecuteNonQuery()
Dim DBDT = New DataTable
Dim DBDA = New SqlDataAdapter(DBCmd)
Dim RecordCount = DBDA.Fill(DBDT)
assignit(DBDT)
DBCon.Close()
Catch ex As Exception
MsgBox(ex.Message)
Finally
If DBCon.State = ConnectionState.Open Then DBCon.Close()
End Try
End Function
Sub assignit(ByVal x As DataTable)
If Me.InvokeRequired Then
Me.Invoke(New delegate_updatedgv(AddressOf assignit))
End If
GridControl1.DataSource = x
End Sub
and its not working at all
回答1:
Your delegate
Private Delegate Sub delegate_updatedgv()
and your method
Sub assignit(ByVal x As DataTable)
don't have the same signature. Actually the compiler already tells you this in an error message...
You could just use Action(Of DataTable)
. There is no need to create a new delegate.
You also needed to set the DataSource only when invoking on the UI thread. You can achieve that by using Else
.
Sub assignit(ByVal x As DataTable)
If Me.InvokeRequired Then
Me.Invoke(New Action(Of DataTable)(AddressOf assignit))
Else
GridControl1.DataSource = x
End If
End Sub
Alternately, you can also declare the delegate properly. Either way
Private Delegate Sub delegate_updatedgv(x As DataTable)
Also, the method / function Private Function load_dgv()
has no return type, and nothing is returned. So it is better suited as a sub.
Private Sub load_dgv()
' ...
End Sub
The compiler also warns you about this.
Pay attention to compiler error messages!
回答2:
While we are at, let's fix up the database code a bit. There is no need to check connection state when database objects are keep local to the method where they are used. This way you can ensure that they are closed and disposed with a Using...End Using
block.
I have no idea why you are calling .ExecuteNonQuery
on this command. You never use RecordCount
so I don't see the point of that either. I just used one line to load the DataTable. The adapter seemed extraneous.
Private Sub load_dgv()
Dim dt As New DataTable
Using DBCon As New SqlConnection("Your connection string"),
DBCmd As New SqlCommand("SELECT * FROM Jobs ", DBCon)
DBCon.Open()
dt.Load(DBCmd.ExecuteReader)
End Using
assignit(dt)
End Sub
I know this didn't answer your threading question but I hope it helped for data access.
Where is the bottleneck in this code? Is it just the retrieval of data or is it updating the UI? Maybe only the data access needs to run on a separate thread.
来源:https://stackoverflow.com/questions/60285369/load-data-from-sql-server-to-datagridview-using-a-thread