请看下面的程序。 我用函数 abc 启动了一个新线程 x,然后我做了一些更长的任务。 为什么 x 只在 end sub 之后开始?它不应该在 sleep 前立即开始吗?
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim x As New Threading.Thread(AddressOf abc)
x.SetApartmentState(Threading.ApartmentState.MTA)
x.Start()
System.Threading.Thread.Sleep(5000)
End Sub
Sub abc()
For i As Integer = 0 To 10 Step 1
Me.lblStatus.Text = "Testing DB connection ( timeout in: " + i.ToString() + "s )"
'Me.StatusStrip1.Invoke(
MsgBox(i.ToString)
System.Threading.Thread.Sleep(1000)
Next
End Sub
编辑:
解决方案是这样的:
(A) 将连接尝试和超时倒计时都放在单独的线程中。
(B) 像这样更新 UI:
If Me.InvokeRequired Then
Me.Invoke(pUpdateStatusMessage, "Successfully connected.")
Else
UpdateStatusMessage("Successfully connected.")
End If
有了这个全局声明,所以不需要传递参数:
Delegate Sub t_pUpdateStatusText(ByVal strMessage As String)
Public pUpdateStatusMessage As t_pUpdateStatusText = New t_pUpdateStatusText(AddressOf UpdateStatusMessage)
Public Sub UpdateStatusMessage(ByVal strMessage As String)
Me.lblStatus.Text = strMessage
Me.StatusStrip1.Update()
End Sub
最佳答案
abc
函数确实会在 Button1_Click
方法结束之前开始。造成困惑的是两件事
首先是您使用以下行直接从后台线程更新 UI
Me.lblStatus.Text = "Testing DB connection ( timeout in: " + i.ToString() + "s )"
此代码不正确,以后可能会导致问题。您必须使用 Invoke 调用才能真正更改 UI。正如您在第二行所做的那样,这将我们带到下一个问题。
Invoke
调用是同步的。它通过本质上将消息推送到 Windows 消息队列并在返回之前等待它被处理来运行。您在主线程中添加的 Thread.Sleep
调用会阻止消息队列实际运行。这有效地停止了后台线程,直到 Sleep
调用完成,给人一种后台线程未运行的感觉。
关于c# - 为什么我的线程没有立即启动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3856942/