parallel.foreach正挂着我的应用程序

时间:2013-02-01 02:57:10

标签: vb.net .net-4.0 parallel-processing task-parallel-library

我有一个 List(MyCustomObject)。此List是TreeView的DataSource。 现在,必须在periodicaly Rising Timer1_Timer事件上更新所有收集的对象。要更新我正在使用 Parallel.ForEach 。这在测试应用程序中工作正常,但最终应用程序在添加计算代码后会挂起,并且可能缺少随机的重复数。请帮忙解决。

Imports System.Threading.Tasks
Imports Telerik.WinControls.UI
Imports System.ComponentModel
Imports System.Threading
Imports Accessibility

Public Class Form1
    Dim WithEvents bw As New BackgroundWorker

    Private Sub Button6_Click(sender As System.Object, e As System.EventArgs) Handles Button6.Click
        Upadte(rt.Nodes.Cast(Of RadTreeNode)())
    End Sub

    Private Shared Sub Upadte(Of T)(source As IEnumerable(Of T))
        Parallel.ForEach(source, New ParallelOptions With {.TaskScheduler =    TaskScheduler.FromCurrentSynchronizationContext, .MaxDegreeOfParallelism = 5}, AddressOf    zUpdate)
    End Sub

    ' Following fragment is a simple example. Real code is more difficult. It includes Network requests, WQL queries e.t.c.
    ' -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Private Shared Sub zUpdate(Of T)(node As T)
        Dim item = TryCast(node, RadTreeNode)
        If item Is Nothing Then
            Return
        End If
        Dim n_node As New RadTreeNode("_" & item.Name)
        n_node.Nodes.Add("Hardware")
        Dim tf As Form = Control.FromHandle(Form1.Handle)
        tf.BeginInvoke(New Action(Function() InlineAssignHelper(item, n_node)))
    End Sub
    ' -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Private Shared Function InlineAssignHelper(ByRef target As RadTreeNode, ByVal value As RadTreeNode) As RadTreeNode
        target.Nodes.Add(value.Clone)
        Return target
    End Function
End Class

创造理念!我会检查一下。顺便说一下,完整代码中没有任何秘密。它只是第一个例子。这是完整的子zUpdate的副本,没有一些典型的查询,在STA中正常工作:

Private Shared Sub zUpdate(Of T)(anode As T)
    Dim searcher As New ManagementObjectSearcher
    Dim tt_node As RadTreeNode = TryCast(anode, RadTreeNode)
    If tt_node Is Nothing Then
        Return
    End If
    Dim t_node As String = tt_node.Name
    Dim n_node As New RadTreeNode With {.Name = "_" & t_node, .Text = "_" & t_node}
    Dim opt As New ConnectionOptions
    opt.Authentication = AuthenticationLevel.PacketPrivacy
    opt.EnablePrivileges = True
    opt.Impersonation = ImpersonationLevel.Impersonate
    opt.Username = CredentialCache.DefaultNetworkCredentials.UserName
    opt.Password = CredentialCache.DefaultNetworkCredentials.Password
    opt.Authority = "ntlmdomain:" & CredentialCache.DefaultNetworkCredentials.Domain
    Dim scope As New ManagementScope("\\" & t_node & "\ROOT\CIMV2", opt)
    Dim query As New ObjectQuery

    If My.Computer.Network.Ping(t_node, 10) = False Then
        Return
        GoTo 1
    End If

    scope.Connect()
    If Not scope.IsConnected Then
        Return
        GoTo 1
    End If

    'Summary
    query.QueryString = "SELECT * FROM Win32_ComputerSystem"
    searcher.Scope = scope
    searcher.Query = query

    n_node.Nodes.Add("Summary")
    For Each queryobj As ManagementObject In searcher.Get
        With n_node.Nodes("Summary")
            .Nodes.Add("Name", "Name:" & queryobj("Name"), 6)
            .Nodes.Add("Domain", "Domain:" & queryobj("Domain"), 6)
            .Nodes.Add("Manufacturer", "Manufacturer:" & queryobj("Manufacturer"), 6)
            .Nodes.Add("Model", "Model:" & queryobj("Model"), 6)
            .Nodes.Add("NumberOfLogicalProcessors", "NumberOfLogicalProcessors:" & queryobj("NumberOfLogicalProcessors").ToString, 6)
            .Nodes.Add("NumberOfProcessors", "NumberOfProcessors:" & queryobj("NumberOfProcessors").ToString, 6)
            .Nodes.Add("TotalPhysicalMemory", "TotalPhysicalMemory:" & queryobj("TotalPhysicalMemory").ToString, 6)
            .Nodes.Add("UserName", "UserName:" & queryobj("UserName"), 6)
            .Nodes.Add("Workgroup", "Workgroup:" & queryobj("Workgroup"), 6)
        End With
    Next

    'LogicalDisk
    query.QueryString = "SELECT * FROM Win32_LogicalDisk"
    searcher.Query = query
    n_node.Nodes.Add("Hardware")
    With n_node.Nodes("Hardware")
        .Nodes.Add("LogicalDisks")
        With .Nodes("LogicalDisks")
            For Each queryobj As ManagementObject In searcher.Get
                .Nodes.Add("Name", "Name" & ": " & queryobj("Name"), 6)
                With .Nodes("Name")
                    .Nodes.Add("Description", "Description: " & queryobj("Description"), 6)
                    .Nodes.Add("DriveType", "DriveType: " & queryobj("DriveType"), 6)
                    .Nodes.Add("Size", "Size: " & queryobj("Size").ToString, 6)
                    .Nodes.Add("FreeSpace", "FreeSpace: " & queryobj("FreeSpace"), 6)
                    .Nodes.Add("VolumeName", "VolumeName: " & queryobj("VolumeName"), 6)
                    .Nodes.Add("VolumeSerialNumber", "VolumeSerialNumber: " & queryobj("VolumeSerialNumber"), 6)
                End With
            Next
        End With

        'network adapters
        query.QueryString = "SELECT * FROM Win32_NetworkAdapterConfiguration"
        searcher.Query = query
        .Nodes.Add("NetworkAdapters")
        With .Nodes("NetworkAdapters")
            For Each queryobj As ManagementObject In searcher.Get
                .Nodes.Add(CStr(queryobj("Description")))
                With .Nodes(CStr(queryobj("Description")))
                    .Nodes.Add("DHCPServer", "DHCPServer: " & queryobj("DHCPServer"), 6)
                    .Nodes.Add("DNSDomain", "DNSDomain: " & queryobj("DNSDomain"), 6)
                    .Nodes.Add("DNSHostName", "DNSHostName: " & queryobj("DNSHostName"), 6)
                    .Nodes.Add("MACAddress", "MACAddress: " & queryobj("MACAddress"), 6)
                    .Nodes.Add("SettingID", "SettingID: " & queryobj("SettingID"), 6)
                End With
            Next
        End With
    End With

    'software
    query.QueryString = "SELECT * FROM Win32_Product"
    searcher.Query = query
    n_node.Nodes.Add("Software")
    With n_node.Nodes("Software")
        For Each queryobj As ManagementObject In searcher.Get
            .Nodes.Add(queryobj("Name"))
            With .Nodes(queryobj("Name"))
                .Nodes.Add("InstallDate", "InstallDate: " & queryobj("InstallDate"), 6)
                .Nodes.Add("IdentifyingNumber", "IdentifyingNumber: " & queryobj("IdentifyingNumber"), 6)
            End With
        Next
    End With

    Dim tf As Form = Control.FromHandle(Form2.Handle)
    tf.BeginInvoke(New Action(Function() InlineAssignHelper(tt_node, n_node)))

1:
    If Not searcher Is Nothing Then
        searcher.Dispose()
        scope = Nothing
    End If
End Sub

Private Shared Function InlineAssignHelper(ByRef target As RadTreeNode, ByVal value1 As RadTreeNode) As RadTreeNode
    Dim t_str As String = Now.Date.ToString & Now.TimeOfDay.ToString

    target.Nodes.Add(t_str)
    target.Nodes(t_str).Nodes.Add(value1.Clone)

    Return target
End Function

1 个答案:

答案 0 :(得分:0)

  

这在测试应用程序中运行良好,但最终应用程序在添加后挂起   计算代码和随机数结果可能不存在。

我怀疑这意味着您的问题可能存在于您未向我们展示的代码中。

最有可能的候选者是真正的 zupdate方法中的代码正在访问某种死锁的共享资源。