Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 调用(委托)挂起应用程序_Vb.net_Multithreading_Threadpool_Invoke - Fatal编程技术网

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是一种更好的方法。