public IEnumerable<string> Simulate(Load workLoad, int threadCount)
 {
     currentTime = new Stopwatch();
     currentTime.Start();
     workLoad.Connect(Enqueue);
     totalMessages = workLoad.TotalMessages;
     dequeueStrategy.Start(threadCount);
     
     Task.Run(() =>
     {
         while (workLoad.TotalSentMessages < workLoad.TotalMessages)
         {
             var before = currentTime.ElapsedMilliseconds;
             workLoad.TimePassed(before);
             var after = currentTime.ElapsedMilliseconds;
             var delay = (int) (after - before);
             if (delay < 50)
             {
                 Thread.Sleep(50 - delay);
             }
         }
         signalEndEvent.Wait();
         taskStarted.Dispose();
         taskEnded.Dispose();
         results.CompleteAdding();
     });
     return results.GetConsumingEnumerable();
 }
        public void TestSlowMessages()
        {
            var workload = new Load()
                .AddStage(1000, 50, () => 60*60*1000);

            var simulator = CreateSimulator();
            var results = simulator.Simulate(workload, 10);
            DumpToConsole(results);
        }
 public IEnumerable<string> Simulate(Load workload, int maximumConcurrency)
 {
     this.maximumConcurrency = maximumConcurrency;
     workload.Connect(queue.Add);
     StartThread(0);
     while (threads.Count > 0)
     {
         workload.TimePassed(currentTime);
         const int longRunningThreshold = 100;
         foreach (var runningThread in threads)
         {
             runningThread.Tick(currentTime);
             var blockedTime = currentTime - runningThread.BlockedAt;
             if (!runningThread.Dead && !runningThread.Replaced && runningThread.ProcessingMessage && blockedTime > longRunningThreshold) //blocked for more than five seconds
             {
                 runningThread.MarkAsReplaced();
                 RampUp();
             }
         }
         foreach (var action in currentQueue)
         {
             action();
         }
         currentQueue.Clear();
         if (threads.Count > 0)
         {
             var newTime = threads.Min(x => x.DueAt);
             if (threads.Any(x => x.LongRunning && !x.Replaced  && newTime - currentTime > longRunningThreshold))
             {
                 currentTime = currentTime + longRunningThreshold;
             }
             else
             {
                 currentTime = newTime;
             }
         }
         //if (!workload.HasMoreMessages && processedMessages == workload.TotalMessages)
         //{
         //    break;
         //}
     }
     return result.Select(x => string.Format("{0,12:n} [{1,2}] {2}", x.Item1, x.Item2, x.Item3));
 }
        public void TestVariableTimes()
        {
            var random = new Random(133);
            var workload = new Load()
                .AddStage(1000, 50, () =>
                {
                    var randomValue = random.Next(100);
                    if (randomValue < 10)
                    {
                        return 12*60*100;
                    }
                    if (randomValue < 30)
                    {
                        return 1*60*100;
                    }
                    return 10;
                });

            var simulator = CreateSimulator();
            var results = simulator.Simulate(workload, 10);
            DumpToConsole(results);
        }