我有一個計時器來制作一個執行緒:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
'ListBox2.Items.Add("Hilo")
hiloCertificador1 = New Thread(AddressOf crearObjeto1)
hiloCertificador1.IsBackground = True
hiloCertificador1.Start()
End Sub
Public Sub crearObjeto1()
UpdateList()
End Sub
Private Delegate Sub UpdateListDelegate()
Private Sub UpdateList()
If Me.InvokeRequired Then
Me.BeginInvoke(New UpdateListDelegate(AddressOf UpdateList))
Else
Dim conn As New SqlConnection(parametrosCon)
Dim cmd = New SqlCommand("SELECT TOP 1 * FROM COLA WHERE docentry < 8654 and enviado = 0", conn)
Dim da As New SqlClient.SqlDataAdapter(cmd)
cmd.Connection.Open()
da.SelectCommand = cmd
da.Fill(dataSet, "Query")
For Each fila As DataRow In dataSet.Tables(0).Rows
cmd = New SqlCommand("UPDATE COLA SET enviado = 1 WHERE DOCENTRY = (@docEntry) AND TIPO = (@tipodoc)", conn)
cmd.Parameters.AddWithValue("@docEntry", fila("docentry"))
cmd.Parameters.AddWithValue("@tipodoc", fila("tipo"))
cmd.ExecuteNonQuery()
Dim factura As New FacturaCerificacion(fila("docentry"), fila("tipo"))
Next
cmd.Connection.Close()
dataSet.Tables("Query").Clear()
End If
End Sub
計時器有一個 4000 的間隔,但是當一個執行緒開始凍結我的 UI 時,我認為是因為行程太大或查詢,但我需要讓它不凍結。
uj5u.com熱心網友回復:
評論是正確的,我會為你描述其中暗示的問題
用一個 System.Windows.Forms.Timer
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
這將在 UI 執行緒上運行,并且僅適用于執行 UI 操作(即使如此,我也不確定您是否真的可以為它辯護System.Threading.Timer)
創建一個新的 System.Threading.Thread
hiloCertificador1 = New Thread(AddressOf crearObjeto1)
hiloCertificador1.IsBackground = True
hiloCertificador1.Start()
這現在運行在 UI 之外,并且是 Timer.Tick 的全部內容。所以你在 UI 上打勾,然后在 UI 上創建了一個新執行緒。這很奇怪
呼叫 Sub 呼叫 Sub
Public Sub crearObjeto1()
UpdateList()
End Sub
Private Sub UpdateList()
' do stuff
End Sub
冗余應該是不言而喻的
做非 UI 的事情,但遵循Control.InvokeRequired/BeginInvoke模式
Private Delegate Sub UpdateListDelegate()
Private Sub UpdateList()
If Me.InvokeRequired Then
Me.BeginInvoke(New UpdateListDelegate(AddressOf UpdateList))
Else
' looks like a bunch of non-UI stuff
End If
End Sub
此模式用于在 UI 上執行操作,但該塊中似乎沒有 UI 代碼。
不使用Using以確保正確處置IDisposable物品
Dim conn As New SqlConnection(parametrosCon)
Dim cmd = New SqlCommand("SELECT TOP 1 * FROM COLA WHERE docentry < 8654 and enviado = 0", conn)
Dim da As New SqlClient.SqlDataAdapter(cmd)
' do stuff
cmd.Connection.Close()
DataSet.Tables("Query").Clear()
與您當前的問題無關,但也很重要。
解決方案
因此,雖然這看起來是一項崇高的努力,但您似乎在 UI 之間來回切換,而不是無緣無故,或者更準確地說,通過過度設計來制造不存在的問題。整個事情可以通過一些小的改變來簡化
用 System.Threading.Timer
Dim Timer2 As New System.Threading.Timer(Sub() UpdateList(), Nothing, -1, -1)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' done in Form_Load if your Timer1 is Enabled in designer
' or can be done in a Button.Click, or however you had enabled Timer1
Timer2.Change(2000, 4000) ' this will enable Timer after 2 seconds, then will tick every 4 seconds
'Timer2.Change(-1, -1) ' this is how it's disabled
End Sub
只需呼叫此方法,并使用它Using來正確處理您的資料庫物件。添加了Sub DoUiStuff()模式是如何正確實作的
Private Sub UpdateList()
Timer2.Change(-1, -1)
Using conn As New SqlConnection(parametrosCon)
conn.Open()
Using cmd = New SqlCommand("SELECT TOP 1 * FROM COLA WHERE docentry < 8654 and enviado = 0", conn)
Using da As New SqlClient.SqlDataAdapter(cmd)
da.SelectCommand = cmd
da.Fill(DataSet, "Query")
For Each fila As DataRow In DataSet.Tables(0).Rows
Using cmdInner = New SqlCommand("UPDATE COLA SET enviado = 1 WHERE DOCENTRY = (@docEntry) AND TIPO = (@tipodoc)", conn)
cmd.Connection.Open()
cmd.Parameters.AddWithValue("@docEntry", fila("docentry"))
cmd.Parameters.AddWithValue("@tipodoc", fila("tipo"))
cmd.ExecuteNonQuery()
Dim factura As New FacturaCerificacion(fila("docentry"), fila("tipo"))
End Using
Next
End Using
End Using
DoUiStuff(arguments) ' for example, if you need to update a GridView
DataSet.Tables("Query").Clear()
End Using
End Sub
Private Sub DoUiStuff(arguments As Whatever)
If Me.InvokeRequired() Then
Me.Invoke(New Action(Of Whatever)(AddressOf DoUiStuff), arguments)
Else
' do UI stuff with arguments
End If
Timer2.Change(2000, -1)
End Sub
最后,為了不自相矛盾,我將添加 Dispose 方法來處理 Timer。默認情況下,此 Sub 將位于您的 Form.Designer.vb 檔案中,您可以將其留在那里或在添加后將其移動到 Form.vb。
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing Then
components?.Dispose()
Timer2?.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/353629.html
上一篇:PostgresRDS資料庫DB連接在星期六無限增加,導致SpringBootJavaAPI應用程式中的“JDBCConnectionException”
下一篇:如何編輯訪問資料庫中的特定物體
