Vb.net 调用(委托)挂起应用程序
我是线程新手,一开始就用Vb.net 调用(委托)挂起应用程序,vb.net,multithreading,threadpool,invoke,Vb.net,Multithreading,Threadpool,Invoke,我是线程新手,一开始就用myThread.Start()手动启动线程。除了关闭状态窗体外,我所有的工作都很好,结束的第一个线程将关闭窗体,而不是最后一个线程。因此,我决定尝试使用QueueUserWorkItem和一个带有handle.waitOne()的循环 现在,当应用程序在Public Sub wol_SearchCompleted()中调用Me.Invoke(disposition)-时,它突然开始挂起。奇怪的是,有时我一步一步地浏览代码,它挂在那行上,有时它工作得很完美 Public
myThread.Start()
手动启动线程。除了关闭状态窗体外,我所有的工作都很好,结束的第一个线程将关闭窗体,而不是最后一个线程。因此,我决定尝试使用QueueUserWorkItem
和一个带有handle.waitOne()
的循环
现在,当应用程序在Public Sub wol_SearchCompleted()中调用Me.Invoke(disposition)
-时,它突然开始挂起。奇怪的是,有时我一步一步地浏览代码,它挂在那行上,有时它工作得很完美
Public Class frmMain
Private wolActiveThreads(Environment.ProcessorCount - 1) As ManualResetEvent 'I have tried setting this to wolActiveThreads(1) but there is no difference
Private adActiveThreads(Environment.ProcessorCount - 1) As ManualResetEvent
Private Sub GetMacAddresses(ByVal compCollection As ComputerCollection)
If compCollection.Count = 0 Then Exit Sub
'Work out how many threads to use and how many computers each thread will discover
Dim numThreads As Integer = wolActiveThreads.Count - 1
Dim remainder As Double = compCollection.Count Mod numThreads
Dim numPerThread As Double = (compCollection.Count - remainder) / numThreads
'Start the threads
For i As Integer = 0 To numThreads - 1
Dim startIndex As Integer = (i * numPerThread)
Dim endIndex As Integer = startIndex + (numPerThread - 1)
IIf(i = numThreads - 1, endIndex = endIndex + remainder, endIndex = endIndex) 'If this is the last thread add the remainder of computers which didn't devide equally
Dim threadParams As Object
threadParams = New Object() {compCollection, startIndex, endIndex} 'Create an object to pass the parameters
Dim n As Integer = i
wolInstances(n) = New WOL(wolActiveThreads(n))
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf wolInstances(n).StartMACSearch), threadParams)
Next
'If the status dialog isn't displayed, display it
If statusDialog Is Nothing Then
statusDialog = New frmStatus
statusDialog.ShowDialog()
End If
End Sub
Private Sub StatusDialogDisposal()
'Wait for all of the ADSearcher class threads to finish
For Each handle As WaitHandle In adActiveThreads
handle.WaitOne()
Next
'Wait for all of the WOL class threads to finish
For Each handle As WaitHandle In wolActiveThreads
handle.WaitOne()
Next
If statusDialog IsNot Nothing Then 'If another thread hasn't already disposed of the dialog
statusDialog.Close() 'Close the dialog
statusDialog.Dispose() 'Dispose of the dialog
statusDialog = Nothing 'Dereference the diposed dialog to prevent errors
End If
End Sub
'[WOL Events]
Private Delegate Sub disposeStatus()
Public Sub wol_SearchCompleted()
Dim disposal As New disposeStatus(AddressOf StatusDialogDisposal)
Me.Invoke(disposal)
End Sub
类别:
Public Class WOL
Public Sub New(ByVal doneEvent As ManualResetEvent)
'Add event handlers
AddHandler Me.MACAddressFound, AddressOf frmMain.wol_MACAddressFound
AddHandler Me.SearchCompleted, AddressOf frmMain.wol_SearchCompleted
_doneEvent = doneEvent
End Sub
Public Sub StartMACSearch(ByVal parameters As Object)
_doneEvent.Reset() 'Make sure the thread pool knows the thread is still working
Dim computerList As ComputerCollection = parameters(0)
Dim startIndex As Integer = parameters(1)
Dim endIndex As Integer = parameters(2)
macsFound = 0
For i As Integer = startIndex To endIndex
GetMACAddress(computerList(i).FQDN)
Next
System.Diagnostics.Debug.Print("Thread " + startIndex.ToString + " to " + endIndex.ToString + " is ending")
RaiseEvent SearchCompleted()
_doneEvent.Set() 'Signal that the thread is finished
End Sub
End Class
所以我需要在自己的线程上显示statusDialog来解决这个问题吗?我读到了对其他人问题的回答,其中说不建议在新线程中创建表单。所有的UI都应该在主线程上运行(虽然它没有解释为什么)。因此,除此之外,我能想到的唯一其他方法是使用if语句手动检查线程的状态并退出子线程,除非它是最后一个线程调用。错误地点击enter并过早发布。下面是它应该说的:我读到了对其他人问题的回答,其中说不建议在新线程中创建表单。所有UI都应该在主线程上运行(尽管没有解释原因)。因此,除此之外,我能想到的唯一其他方法是使用if语句手动检查线程的状态并退出sub,除非它是最后一个线程调用,然后调用表单处理(而不是handle.WaitOne())。但我不知道这是否是一个好的做法?(或者如果可能的话)或将等待线程的循环移动到WOL类中,并在引发SearchCompleted事件之前等待线程完成。但这意味着要跨线程访问wolActiveThreads数组,我假设我可以通过调用一个函数来实现,该函数将通过线程传递数组。但我也不知道这是否有效,或者这是否是一种良好的做法?直到明天晚上我才有时间尝试这些选项,但如果有人能建议最好的选项,我将不胜感激。您是否使用.NET3.5或更高版本?如果是这样的话,任务API是一种更好的方法。