我看过很多关于控制问题的帖子。禁止挂起应用程序,但它们似乎主要限于那些在.NET 1.1上运行的应用程序。我也看到了使用.BeginInvoke的建议,而不是我试过但无济于事。 .BeginInvoke不会挂起但它也不会调用委托。我主要担心的是,我已经使用.Invoke多年没有任何问题,我在该领域有一个主要的应用程序广泛使用它,我担心这个问题会出现在那里。就我的工作代码和失败的代码而言,我没有做任何不同的事情。我写了一段简单的代码来复制这个问题(全部在4.0 VS2010中):
Public Class Form1
Private WithEvents sat As TestInvoke
Private Delegate Sub doTheUpdateDelegate(ByVal message As String)
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
sat = New TestInvoke
sat.startAThread()
End Sub
Public Class TestInvoke
Public Event UpdateControl()
Public Sub startAThread()
Dim t As New Threading.Thread(AddressOf _startAThread)
Dim trace As String
trace = "a"
t.SetApartmentState(Threading.ApartmentState.STA)
t.Start()
t.Join()
End Sub
Protected Sub _startAThread()
Try
For k = 0 To 10
System.Threading.Thread.Sleep(1000)
k += 1
RaiseEvent UpdateControl()
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class
Private Sub sat_UpdateControl() Handles sat.UpdateControl
Try
Call doTheupdate(Now.ToString)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub doTheUpdate(ByVal message As String)
Try
If Button1.InvokeRequired = True Then
Dim objParams As Object() = {message}
'hangs on the following line
Button1.Invoke(New doTheUpdateDelegate(AddressOf doTheUpdate), objParams)
Else
Button1.Text = message
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class
如果有人能在这里看到我做错了什么,我真的很感激!
答案 0 :(得分:10)
只有一个原因导致Control.Invoke()调用挂起。或者BeginInvoke()调用不执行其目标,同样的事情。当程序的主线程(UI线程)没有空闲并忙于执行其他操作时,就会发生这种情况。
整个地图上的“别的东西”是什么。你可以做的最糟糕的事情是主线程等待工作线程完成。如果你使用Invoke(),这是一个保证死锁。
条件很容易诊断,使用Debug + Break All和Debug + Windows + Threads。双击主线程并查看“调用堆栈”窗口。堆栈跟踪的顶部应该说“Managed to Native Transition”,它下面的那个应该是FPushMessageLoop()。如果您看到其他内容,那么您已找到导致死锁的代码。
答案 1 :(得分:1)
您正在使用Thread.Join
让UI线程暂停,直到另一个线程完成。同时使用Control.Invoke
让UI线程执行某些操作。这不会起作用,因为UI线程正在等待另一个线程完成。
如果您希望等待操作完成,我建议您删除Thread.Join
调用或在UI线程中执行操作。