繁体   English   中英

并行运行任务,其中一些是连续运行的

[英]Run tasks in parallel and some of them consecutively

我想并行运行方法 A 和方法 B1。 这是有效的。 但是如何在 B1 完成后运行方法 B2?

    class Program
    {
        static void Main(string[] args)
        {
            //var firstTask = Task.Factory.StartNew(() => MethodB1());
            //var secondTask = firstTask.ContinueWith( (antecedent) => MethodB2());

            Action[] actionsArray =
            {
                () => MethodA(),
                () => MethodB1(),
            };

            Parallel.Invoke(actionsArray);
        }

        private static void MethodA()
        {
            Console.WriteLine("A");
            // more code is running here (30 min)
        }

        private static void MethodB1()
        {
            Console.WriteLine("B1");
            // more code is running here (2 min)
        }

        private static void MethodB2()
        {
            Console.WriteLine("B2");
        }
    }

编辑:我希望下面的例子能阻止混乱。 ;)

A -> A -> A -> A -> A -> A -> A -> A -> A -> A -> A -> A -> A -> A
B1 -> B1 -> B1 -> B1 -> B1 -> B2 -> B2 -> B2

C# 是一种很好的语言来做到这一点,有很多方法可以做到这一点,正如评论所暗示的,另一种是这样的:

static void Main()
{
    var t = MethodA();
    MethodB1().ContinueWith((r) =>
    MethodB2()).Wait();
    t.Wait();
}

private static async Task MethodA()
{
    await Task.Run(() =>
    {
        for (int i = 0; i < 40; i++)
        {
            Thread.Sleep(100);
            Console.WriteLine("A");
        }
    });
}

private static async Task MethodB1()
{
    await Task.Run(() =>
    {
        for (int i = 0; i < 10; i++)
        {
            Thread.Sleep(100);
            Console.WriteLine("B1");
        }
    });
}

private static void MethodB2()
{
    for (int i = 0; i < 10; i++)
    {
        Thread.Sleep(100);
        Console.WriteLine("B2");
    }
}

您可以使用ContinueWith轻松实现此目的。 这是代码

 public static void Main(string[] args)
 {
     var t1 = Task.Factory.StartNew(MethodA);           
     var t2 = Task.Factory.StartNew(MethodB1).ContinueWith(task => MethodB2());   
     Task.WaitAll(t1, t2); // If you want to wait here for finishing the above tasks                                           
 }

要描述输出,您可以尝试使用MethodAMethodB1MethodB2的以下实现

private static void MethodA()
{
    for (int i = 0; i < 100; i++)
    {
        Console.Write("A ");
        Thread.Sleep(100);
    }  
}

private static void MethodB1()
{

    for (int i = 0; i < 100; i++)
    {
        Console.Write("B1 ");
        Thread.Sleep(100);
    }
}

private static void MethodB2()
{
    for (int i = 0; i < 100; i++)
    {
        Console.Write("B2 ");
        Thread.Sleep(100);
    }
}

这不适用于 VS2017 及更新版本,因为 VS2017 之前的控制台应用主干线不支持 async 关键字。 在旧版本中,您应该执行Task.WhenAll().Wait();而不是await Task.WhenAll() Task.WhenAll().Wait();

namespace ConsoleApp3
{
    class Program
    {
        static async void Main(string[] args)
        {
            var taskA = Task.Run(() => MethodA()); //Start runnning taskA
            var taskB1AndB2 = Task.Run(() => MethodB1()).ContinueWith(async (taskb1) => { await taskb1; await Task.Run(()=>MethodB2()); }).Unwrap(); //When taskB1 is complete, continue with taskB2
            await Task.WhenAll(taskA, taskB1AndB2); //wait until all 3 tasks are completed
        }

        private static void MethodA()
        {
            Console.WriteLine("A");
            // more code is running here (30 min)
        }

        private static void MethodB1()
        {
            Console.WriteLine("B1");
            // more code is running here (2 min)
        }

        private static void MethodB2()
        {
            Console.WriteLine("B2");
        }
    }
}

一种方法是委托回调机制类程序。 另一种可以是基于事件的Here is Used First 方法。 给定时间样本

这正是你想要的

class Program
{

    static System.Collections.Concurrent.ConcurrentQueue<Action> leftOvers = new System.Collections.Concurrent.ConcurrentQueue<Action>();
    static void Main(string[] args)
    {


        for (int i = 0; i < 100; i++)
        {
            Task.WaitAll(MethodA(), MethodB1(MethodB2));
        }

        Action callBack = null;
        while (leftOvers.TryDequeue(out callBack))
        {
            callBack();
        }
        Console.ReadLine();
    }

    private static void QueueMethods(Action method)
    {
        leftOvers.Enqueue(method);
    }

    private async static Task MethodA()
    {
        await Task.Run(() => Console.WriteLine("A  at" +  DateTime.Now.TimeOfDay ));

    }


    private async static Task MethodB1(Action callBack)
    {
        await Task.Run(() => Console.WriteLine("B1 at" + DateTime.Now.TimeOfDay));
        leftOvers.Enqueue(callBack);

    }

    private  static void MethodB2()
    {
        Console.WriteLine("B2 at" + DateTime.Now.TimeOfDay);

    }
}

只需在 Parallel.Invoke 之后添加 B2。 Parallel.Invoke 在进入下一行之前等待完成。 https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-use-parallel-invoke-to-execute-parallel-operations

    public static void Main(string[] args)
    {
        Action[] actionsArray =
        {
            () => MethodA(),
            () => MethodB1()
        };

        Parallel.Invoke(actionsArray);
        MethodB2();
    }

    private static void MethodA()
    {
        Console.WriteLine("A");
        Thread.Sleep(3000);
        // more code is running here (30 min)
    }

    private static void MethodB1()
    {
        Console.WriteLine("B1");
        Thread.Sleep(200);
        // more code is running here (2 min)
    }

    private static void MethodB2()
    {
         Console.WriteLine("B2");
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM