2017-11-13 20 views
-2

私はいくつかのタスクを並列に実行するコンソールアプリケーションを持っています。私の場合、重要なのは、タスクを同時に完了したいということです。私はどのくらいの時間を要するかを知っています。そのため、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 . . . 

どのサービスがループ内でzであるかを区別し、z.DoWork()を呼び出す前にカスタムThread.Sleepを追加しますが、私はlookinですgよりスマートなソリューション

+0

単にすべてのタスクが同時に完了することは保証できません。ただし、続行する前にそれらのすべてが完了するのを待つことができます。 Task.WaitAll()のドキュメントを見てください。 – legrojan

+0

複数の完全に異なる並列化パラダイムを同時に使用しないでください。 *タスクを使用するか、*または* Parallelクラスを使用します。両方を使用しないでください。 'Task'コンストラクタも使うべきではありません。スレッドプールスレッドでいくつかの関数を実行する 'Task'を作成したい場合は、代わりに' Task.Run'を使って既に開始したタスクを作成してください。 – Servy

+0

私はそれらが同時に完了するのは望ましくないが、ほぼ同じ時間に数ミリ秒の差を付けて – IIvanov

答えて

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)はいくつかの時間のかかる操作を表します。

関連する問題