如何:使用并行任务遍历二叉树

下面的示例演示并行任务可用于遍历树数据结构的两种方式。 创建树自身作为练习留给您来做。

示例

Imports System.Threading.Tasks

Public Class TreeWalk

    Shared Sub Main()

        Dim tree As Tree(Of Person) = New Tree(Of Person)()

        ' ...populate tree (left as an exercise)

        ' Define the Action to perform on each node.
        Dim myAction As Action(Of Person) = New Action(Of Person)(Sub(x)
                                                                      Console.WriteLine("{0}  : {1} ", x.Name, x.Number)
                                                                  End Sub)

        ' Traverse the tree with parallel tasks.
        DoTree(tree, myAction)
    End Sub

    Public Class Person

        Public Name As String
        Public Number As Integer
    End Class

    Public Class Tree(Of T)

        Public Left As Tree(Of T)
        Public Right As Tree(Of T)
        Public Data As T
    End Class



    ' By using tasks explicitly.
    Public Shared Sub DoTree(Of T)(ByVal myTree As Tree(Of T), ByVal a As Action(Of T))

        If Not myTree Is Nothing Then
            Return
        End If
        Dim left = Task.Factory.StartNew(Sub() DoTree(myTree.Left, a))
        Dim right = Task.Factory.StartNew(Sub() DoTree(myTree.Right, a))
        a(myTree.Data)

        Try

            Task.WaitAll(left, right)

        Catch ae As AggregateException

            'handle exceptions here
        End Try
    End Sub

    ' By using Parallel.Invoke
    Public Shared Sub DoTree2(Of T)(ByVal myTree As Tree(Of T), ByVal myAct As Action(Of T))

        If Not myTree Is Nothing Then
            Return
        End If
        Parallel.Invoke(
            Sub() DoTree2(myTree.Left, myAct),
            Sub() DoTree2(myTree.Left, myAct),
            Sub() myAct(myTree.Data)
        )
    End Sub

End Class
    public class TreeWalk
    {
        static void Main()
        {
            Tree<MyClass> tree = new Tree<MyClass>();

            // ...populate tree (left as an exercise)

            // Define the Action to perform on each node.
            Action<MyClass> myAction = x => Console.WriteLine("{0} : {1}", x.Name, x.Number);

            // Traverse the tree with parallel tasks.
            DoTree(tree, myAction);
        }

        public class MyClass
        {
            public string Name { get; set; }
            public int Number { get; set; }
        }
        public class Tree<T>
        {
            public Tree<T> Left;
            public Tree<T> Right;
            public T Data;
        }



        // By using tasks explcitly.
        public static void DoTree<T>(Tree<T> tree, Action<T> action)
        {
            if (tree == null) return;
            var left = Task.Factory.StartNew(() => DoTree(tree.Left, action));
            var right = Task.Factory.StartNew(() => DoTree(tree.Right, action));
            action(tree.Data);

            try
            {
                Task.WaitAll(left, right);
            }
            catch (AggregateException )
            {
                //handle exceptions here
            }
        }

        // By using Parallel.Invoke
        public static void DoTree2<T>(Tree<T> tree, Action<T> action)
        {
            if (tree == null) return;
            Parallel.Invoke(
                () => DoTree2(tree.Left, action),
                () => DoTree2(tree.Right, action),
                () => action(tree.Data)
            );
        }

    }

演示的这两种方法在功能上等效。 通过使用 StartNew() 方法来创建和运行任务,您可以获取从任务返回的句柄,该句柄可用于等待任务和处理异常。

请参见

概念

任务并行库