在不同时间执行并行任务

时间:2017-11-13 14:38:52

标签: c# .net multithreading task-parallel-library

我有控制台应用程序并行执行几项任务。在我的情况下,重要的是我希望任务同时完成。我知道每项任务要花多长时间。因此,想法是以某种方式延迟Parallel.ForEach中的每个任务,每个任务具有自定义时间延迟,因此它们都在同一时间完成,并且最终所有任务将与花费大部分时间的任务同时完成。

示例:

interface IService
{
    void DoWork();
}

class Program
{
    static void Main(string[] args)
    {
        var services = new List<IService>();
        services.Add(new ServiceA());//Takes 500ms to DoWork()
        services.Add(new ServiceB());//Takes 1000ms to DoWork()
        services.Add(new ServiceC());//Takes 5000ms to DoWork()

        Parallel.ForEach(services, z =>
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            z.DoWork();
            Console.WriteLine($"Ready for {sw.Elapsed}");
        });
    }
}

输出:

Ready for 00:00:00.5006837
Ready for 00:00:01.0002284
Ready for 00:00:05.0010202
Press any key to continue . . .

如何修改代码,使输出如下:

Ready for 00:00:05.5006837
Ready for 00:00:05.0002284
Ready for 00:00:05.0010202
Press any key to continue . . .

我想最明显的解决方案是在循环中区分哪个Service是z并在调用z.DoWork()之前添加自定义Thread.Sleep,但我正在寻找更智能的解决方案。

1 个答案:

答案 0 :(得分:1)

感谢您的帮助!所以这就是我想要实现的目标。所有服务同时完成他们的工作。这是正确的做法吗?

class Program
{
    static void Main(string[] args)
    {
        ServiceA a = new ServiceA();
        ServiceB b = new ServiceB();
        ServiceC c = new ServiceC();

        int maxDelay = 3000;
        var sw = new Stopwatch();
        sw.Start();

        Task taskA = Task.Delay(maxDelay - a.ResponseTime).ContinueWith(x =>
          {
              a.DoWork();
              Console.WriteLine($"taskA ready for {sw.Elapsed}");
          });

        Task taskB = Task.Delay(maxDelay - b.ResponseTime).ContinueWith(x =>
          {
              b.DoWork();
              Console.WriteLine($"taskB ready for {sw.Elapsed}");
          });

        Task taskC = Task.Delay(maxDelay - c.ResponseTime).ContinueWith(x =>
        {
            c.DoWork();
            Console.WriteLine($"taskC ready for {sw.Elapsed}");
        });

        taskA.Wait();
        taskB.Wait();
        taskC.Wait();

        Console.WriteLine(sw.Elapsed);
    }
}

class ServiceA
{
    public int ResponseTime { get => 500; }
    public void DoWork() => Thread.Sleep(500);
}

class ServiceB
{
    public int ResponseTime { get => 1000; }
    public void DoWork() => Thread.Sleep(1000);
}

class ServiceC
{
    public int ResponseTime { get => 3000; }
    public void DoWork() => Thread.Sleep(3000);
}

输出:

taskA ready for 00:00:03.0084344
taskC ready for 00:00:03.0102184
taskB ready for 00:00:03.0102588

* Thread.Sleep(x)表示一些耗时的操作。