Пример #1
0
        private static void Run(int n, int threadCount)
        {
            Dispatcher d = new Dispatcher(threadCount, "ccr pool");
            DispatcherQueue dq = new DispatcherQueue("disp", d);
            Port<int> p1 = new Port<int>(),  p2 = new Port<int>();
            EventWaitHandle done1 = new AutoResetEvent(false), done2 = new AutoResetEvent(false);

            PingPonger pp1 = new PingPonger(done1, n, p2),
                pp2 = new PingPonger(done2, n, p1);

            Arbiter.Activate(dq, Arbiter.Interleave(
                new TeardownReceiverGroup(),
                new ExclusiveReceiverGroup(Arbiter.Receive(true, p1, pp1.Update)),
                new ConcurrentReceiverGroup()));

            Arbiter.Activate(dq, Arbiter.Interleave(
                new TeardownReceiverGroup(),
                new ExclusiveReceiverGroup(Arbiter.Receive(true, p2, pp2.Update)),
                new ConcurrentReceiverGroup()));

            p1.Post(0);

            EventWaitHandle.WaitAll(new[] { done1, done2 });

            dq.Dispose();
            d.Dispose();
        }
Пример #2
0
        public void DispatchEventWithDispatcherQueueExceptionPort()
        {
            using (Dispatcher d = new Dispatcher ()) {
                var dq = new DispatcherQueue ("foo", d);
                var evt = new AutoResetEvent (false);
                var port = new Port<Exception> ();
                dq.UnhandledExceptionPort = port;

                int portPost = 0;
                int dispEx = 0;
                d.UnhandledException += delegate { ++dispEx; };

                var rec = Arbiter.Receive (true, port, (e) => { ++portPost; evt.Set(); });
                rec.TaskQueue = dq;
                rec.Execute ();

                dq.Enqueue (Arbiter.FromHandler (() => { throw new Exception (); }));
                Assert.IsTrue (evt.WaitOne (2000), "#1");
                Assert.AreEqual (1, portPost, "#2");
                Assert.AreEqual (0, dispEx, "#3");

                dq.Enqueue (Arbiter.FromHandler (() => { throw new Exception (); }));
                Assert.IsTrue (evt.WaitOne (2000), "#4");
                Assert.AreEqual (2, portPost, "#5");
                Assert.AreEqual (0, dispEx, "#6");
            }
        }
Пример #3
0
            ///////////////////////////////////////////////////////////////////
            // if if{(join1) (expr0)}else{&element}
            // if1 if{expr1 - &element0}elseif{&join1}else{&element}
            // expr00 - if0 if{expr2 - element0}elseif{expr3 - &element0}elseif{[(expr5 - join)(expr4 - &join)] - element1}elseif{[(expr50 - join0)(expr40 - &join0)] - &element1}else{element}
            // [(__use__3.snippet.snippet.noop - __use__3.snippet.snippet.expr - __use__3.snippet.snippet.join)] - __use__3.snippet.call - __use__3.snippet.call.iftype
            // __use__50.snippet.snippet.noop - [(__use__50.snippet.snippet.expr0 - __use__50.snippet.snippet.join)(__use__50.snippet.snippet.expr - &__use__50.snippet.snippet.join)] - __use__50.snippet.call - __use__50.snippet.call.iftype
            // __use__5.snippet0.snippet.noop - [(__use__5.snippet0.snippet.expr0 - __use__5.snippet0.snippet.join)(__use__5.snippet0.snippet.expr - &__use__5.snippet0.snippet.join)] - __use__5.snippet0.call - __use__5.snippet0.call.iftype
            ///////////////////////////////////////////////////////////////////

            public OnSpeechRecognizerSpeechRecognizedHandler(DiagramService service, ccr.DispatcherQueue queue)
                : base(service, queue)
            {
                // Activate merge handlers
                Activate(ccr.Arbiter.Receive(true, _mergeAlpha, _mergeAlphaHandler));
                Activate(ccr.Arbiter.Receive(true, _mergeBeta, _mergeBetaHandler));
                Activate(ccr.Arbiter.Receive(true, _mergeGamma, _mergeGammaHandler));

                RegisterAndActivateJoins();
            }
Пример #4
0
 public ThrottledQueue(string threadPoolName, string dispatcherQueueName, 
     PostMessageDelegate postMessage, int maxPoolItemReuse)
 {
     matchMaker = new MatchMaker(maxPoolItemReuse);
     dispatcher = new Dispatcher(1, threadPoolName);
     dispatcherQueue = new DispatcherQueue(dispatcherQueueName, dispatcher);
     messagePort = new Port<QueueItem>();
     Handler<QueueItem> handler = new Handler<QueueItem>(postMessage);
     Arbiter.Activate(dispatcherQueue, Arbiter.Receive(true, messagePort, handler));
 }
Пример #5
0
        static void ParallelIntegration(dynamic step, dynamic Low, dynamic Up, ScriptScope scope)
        {
            // создание массива объектов для хранения параметров
            InputData[] ClArr = new InputData[nc];
            for (int i = 0; i < nc; i++)
                ClArr[i] = new InputData();

            //Далее, задаются исходные данные для каждого экземпляра
            //вычислительного метода:
            // заполняем массив параметров
            dynamic Low_temp = Low;
            for (int i = 0; i < nc; i++)
            {
                ClArr[i].start = Low_temp;
                if (i + 1 == nc)
                    ClArr[i].stop = Up;
                else
                    ClArr[i].stop = Low_temp + step;

                Low_temp = Low_temp + step;
            }
            //Создаётся диспетчер с пулом из двух потоков:
            Dispatcher d = new Dispatcher(nc, "Test Pool");
            DispatcherQueue dq = new DispatcherQueue("Test Queue", d);
            //Описывается порт, в который каждый экземпляр метода Int()
            //отправляет сообщение после завершения вычислений:
            Port<int> p = new Port<int>();
            //Метод Arbiter.Activate помещает в очередь диспетчера две задачи(два
            //экземпляра метода Mul):

            System.Diagnostics.Stopwatch ssWatch = new System.Diagnostics.Stopwatch();
            ssWatch.Start();

            for (int i = 0; i < nc; i++)
                Arbiter.Activate(dq, new Task<InputData, Port<int>, ScriptScope>(ClArr[i], p, scope, Int));
            //Первый параметр метода Arbiter.Activate – очередь диспетчера,
            //который будет управлять выполнением задачи, второй параметр –
            //запускаемая задача.
            //С помощью метода Arbiter.MultipleItemReceive запускается задача
            //(приёмник), которая обрабатывает получение двух сообщений портом p:
            Arbiter.Activate(dq, Arbiter.MultipleItemReceive(true, p, nc, delegate (int[] array)
            {
                Console.WriteLine("Вычисления завершены");
                ssWatch.Stop();
                Console.WriteLine("Полное время работы {0} мс", ssWatch.ElapsedMilliseconds.ToString());
                Console.ReadKey(true);
                Environment.Exit(0);
            }));
            

            
            Console.ReadKey(true);
            Environment.Exit(0);
        }
Пример #6
0
        public ReloadDialog(ReloadConfig reloadConfig, IForwardLinkManagement transport, Node nexthopnode) {
            this.m_NextHopNode = nexthopnode;
            this.m_Transport = transport;
            this.m_fDone = new Port<bool>();
            this.m_DispatcherQueue = reloadConfig.DispatcherQueue;
            this.m_ReloadConfig = reloadConfig;
            m_Transport.ReloadFLMEventHandler += new ReloadFLMEvent(OVL_ReloadForwardLinkManagementEventHandler);

            if(nexthopnode.IceCandidates == null)
                throw new System.Exception(String.Format("ReloadDialog: no ice candidates for {0} ", nexthopnode.Id));
        }
Пример #7
0
        /// <summary>
        /// Initializes new instance with specified path used for loading processing nodes, and number of worker threads
        /// </summary>
        /// <param name="path"></param>
        public AlgoGrid(string path, int workerThreadCount)
        {
            m_dispatcher = new Dispatcher(workerThreadCount, "ThreadPool");
            m_dispatcherQueue = new DispatcherQueue("Queue", m_dispatcher);
            m_queue = new Port<IBaseItem>();
            ITask task = Arbiter.Receive(true, m_queue, InnerHandle);
            Arbiter.Activate(m_dispatcherQueue, task);

            DirectoryCatalog catalog = new DirectoryCatalog(path);
            CompositionContainer container = new CompositionContainer(catalog);
            container.SatisfyImportsOnce(this);
        }
Пример #8
0
            static void Main(string[] args)
        {
            int i;
            nc = 4;// количество ядер
            n = 100000000;

            Arr = new int[n];
            int Result = 0;

            Random r = new Random();
            for (int j = 0; j < n; j++)
                Arr[j] = r.Next(5);

            System.Diagnostics.Stopwatch sWatch = new System.Diagnostics.Stopwatch();
            sWatch.Start();
            for (i = 9; i < n; i++)//последовательный алгоритм
            {
                Result = Result + Arr[i];
            }

            Console.WriteLine("Сумма:");
            Console.WriteLine(Result);

            sWatch.Stop();
         
            Console.WriteLine("Последовательный алгоритм = {0} мс.", sWatch.ElapsedMilliseconds.ToString());


            InputData[] ClArr = new InputData[nc];// создание массива объектов для хранения параметров 
            for (i = 0; i < nc; i++)
                ClArr[i] = new InputData();

            int step = (Int32)(n / nc); // делим количество элементов  в массиве на nc частей 
            
            int c = -1;
            for (i = 0; i < nc; i++)// заполняем массив параметров 
            {
                ClArr[i].start = c + 1;
                ClArr[i].stop = c + step;
                ClArr[i].i = i;
                c = c + step;
            }
            Dispatcher d = new Dispatcher(nc, "Test Pool");
            DispatcherQueue dq = new DispatcherQueue("Test Queue", d);
            Port<int> p = new Port<int>();

            for (i = 0; i < nc; i++)
                Arbiter.Activate(dq, new Task<InputData, Port<int>>(ClArr[i], p, Sum));

            Arbiter.Activate(dq, Arbiter.MultipleItemReceive(true, p, nc, delegate(int[] array)
     {   }));}}}
Пример #9
0
		internal Node(RelayNodeDefinition nodeDefinition, NodeGroup ownerGroup, NodeCluster ownerCluster, ForwardingConfig forwardingConfig, DispatcherQueue inMessageQueue, DispatcherQueue outMessageQueue)
		{
			DetectedZone = 0;
			NodeDefinition = nodeDefinition;
			NodeGroup = ownerGroup;
			NodeCluster = ownerCluster;
			_messageCounts = new int[RelayMessage.NumberOfTypes];
			_lastMessageTimes = new double[RelayMessage.NumberOfTypes];
			_averageMessageTimes = new double[RelayMessage.NumberOfTypes];
			if (EndPoint != null)
			{
				_transport = TransportFactory.CreateTransportForNode(nodeDefinition, ownerGroup.GroupDefinition, forwardingConfig.MessageChunkLength);
				DetectedZone = NodeManager.Instance.GetZoneForAddress(EndPoint.Address);
				if (forwardingConfig.MapNetwork)
				{
					HopsFromHere = HowManyHopsFromHere();
				}
				else
				{
					HopsFromHere = 0;
				}
			}
			else
			{
				_transport = new NullTransport();
			}

			_inMessageQueue = inMessageQueue;
			_outMessageQueue = outMessageQueue;

			if (forwardingConfig != null)
			{
				_messageBurstLength = forwardingConfig.MessageBurstLength;
				_messageBurstTimeout = forwardingConfig.MessageBurstTimeout;
				_messageBurstTimeoutSpan = TimeSpan.FromMilliseconds(_messageBurstTimeout);
				MessageErrorQueue = new MessageQueue(ownerGroup.GetQueueConfig());
				_repostMessageLists = forwardingConfig.RepostMessageLists;
			}

			ActivateBurstReceive(1); //the burst length will be used after the first message is received

			// async, no skipping of the error queue (duh)
			Arbiter.Activate(_inMessageQueue,
				Arbiter.Receive<List<SerializedRelayMessage>>(true, _inMessagesPort,
															  messages => DoHandleInMessages(messages, false)));

			Arbiter.Activate(_outMessageQueue,
				Arbiter.Receive<MessagesWithLock>(true, _outMessagesPort,
				delegate(MessagesWithLock messages) { HandleOutMessages(messages.Messages); messages.Locker.Decrement(); }));
		}
Пример #10
0
        //Метод параллельной сортировки массива
        static void parral_qsort(int[] a, int left, int right)
        {
            //Создаём диспетчеры
            Dispatcher d = new Dispatcher(2, " Test Pool");
            DispatcherQueue dq = new DispatcherQueue(" Test Queue", d);

            //Описываем порт
            Port<int> p = new Port<int>();

            //Первый этап параллельной сортировки
            //Параллельно сортируются две половины массива
            InputData data = new InputData();
            data.str = "Первая половина массива ";
            data.array = a; data.start = 0; data.stop = right/2 + 1;
            Arbiter.Activate(dq, new Task<InputData, Port<int>>(data, p, thread_fun));
            Console.WriteLine("Первый этап");
            Console.ReadKey();
            data.str = "Вторая половина массива ";
            data.array = a; data.start = right/2 + 1; data.stop = right;
            Arbiter.Activate(dq, new Task<InputData, Port<int>>(data, p, thread_fun));
            Console.ReadKey();

            //Второй этап параллельной сортировки
            //Сортируется центральная часть массива
            Console.WriteLine();
            Console.WriteLine("Второй этап");
            Stopwatch sWatch = new Stopwatch();
            sWatch.Start();
            qsort(a,right/4,right/4+right/2 +1);
            sWatch.Stop();
            Console.WriteLine("Средняя часть массива   Время работы: " + sWatch.ElapsedMilliseconds);
            Console.ReadKey();

            //Третий этап параллельной сортировки
            //Параллельно сортируются две половины массива
            data.str = "Первая половина массива ";
            data.array = a; data.start = 0; data.stop = right / 2 + 1;
            Arbiter.Activate(dq, new Task<InputData, Port<int>>(data, p, thread_fun));
            Console.WriteLine("Первый этап");
            Console.ReadKey();
            data.str = "Вторая половина массива ";
            data.array = a; data.start = right / 2 + 1; data.stop = right;
            Arbiter.Activate(dq, new Task<InputData, Port<int>>(data, p, thread_fun));
            Console.ReadKey();
            return;
        }
Пример #11
0
        static void ParallelShellSort()
        {
            Dispatcher dispatcher = new Dispatcher(arraySize, "THREAD_POOL");
            DispatcherQueue dsipQueue = new DispatcherQueue("Dispatcher", dispatcher);

            Port<int> port = new Port<int>();

            for (int i = 0; i < arraySize; ++i)
            {
                Data d = new Data();
                d.row = i;
                Arbiter.Activate(dsipQueue, new Task<Data, Port<int>>(d, port, Task));

            }

            return;
        }
Пример #12
0
        /// <summary>
        /// Constructor for the class.
        /// </summary>
        /// <param name="portName">The port for communication</param>
        /// <param name="queue">The robotics runtime DispatcherQueue</param>
        public MotorControl(string portName, DispatcherQueue queue, GenericMotorService b)
        {
            myMotors = new SerialPort();
            state = 0;
            receive_ack = "";
            dq = queue;
            motorAckRecieve = new
                PortSet<SendAck, Stop, Turn, SetSpeed, StopComplete, TurnComplete, BumperActivated>();
            bumper = b;
            //Initialize Serial Port Parameters
            myMotors.PortName = portName;
            myMotors.BaudRate = DEFAULT_BAUD_RATE;
            myMotors.Parity = DEFAULT_PARITY;
            myMotors.DataBits = DEFAULT_DATA_BITS;
            myMotors.StopBits = DEFAULT_STOP_BITS;
            myMotors.Handshake = DEFAULT_HANDSHAKE;

            myMotors.ReadTimeout = DEFAULT_TIMEOUT;
            myMotors.WriteTimeout = DEFAULT_TIMEOUT;
        }
Пример #13
0
        /// <summary>
        /// Call to initialize the control and start threads.  The main GUI 
        /// </summary>
        public void Start()
        {
            queue = new DispatcherQueue("SimulatorDisplay", new Dispatcher());
            throttledQueue = new DispatcherQueue("SimulatorDisplayThrottled", new Dispatcher(1, "SimulatorDisplayThrottled"), TaskExecutionPolicy.ConstrainQueueDepthDiscardTasks, 2);

            // Start a thread that will wait one second, check for the SimulatorEngine,
            // and start another check thread if it is not found, or trigger the
            // SimulatorFound event if it is found.
            ParameterizedThreadStart checker = new ParameterizedThreadStart(
                delegate(object next)
                {
                    //Console.WriteLine("Checking for simulator...");
                    if (checkSimulator() == false)
                    {
                        Thread.Sleep(TimeSpan.FromSeconds(1));
                        new Thread((ParameterizedThreadStart)next).Start(next);
                    }
                });
            new Thread(checker).Start(checker);

            Arbiter.Activate(queue, Arbiter.Receive(false, sizeChangePort, SizeChangeHandler));
        }
Пример #14
0
		internal MessageTracer(short maxTypeId, TraceSettings traceSettings)
		{
			//dispatchers and dispatcher queues need unique names. it's unlikely that a single class could want more than one of these.
			//blatantly stolen from mr custenborders logwrapper class
			string name = ExtractClassName(new StackFrame(1).GetMethod()); 

			_sampleTimer = new Timer(SampleTimerCallback);

			ReloadConfig(maxTypeId, traceSettings);

			_traceDispatcher = new Dispatcher(1, ThreadPriority.BelowNormal, true, name + "TraceDispatcher"); //using only 1 thread keeps us from needing any locking on the stream output

			_traceMessageQueue = new DispatcherQueue(name + "DispatcherQueue", _traceDispatcher, 
				TaskExecutionPolicy.ConstrainQueueDepthDiscardTasks, 10000);

			Arbiter.Activate(_traceMessageQueue,
								Arbiter.Receive<RelayMessage>(true, _tracePort, DoWriteTraceInfo));
			
			Arbiter.Activate(_traceMessageQueue,
						Arbiter.Receive<IList<RelayMessage>>(true, _traceListPort, DoWriteTraceInfo));

			Arbiter.Activate(_traceMessageQueue,
				Arbiter.Receive<string>(true, _stringPort, DoWriteTraceInfo));
		}
Пример #15
0
        // markus end


        public ReloadFLM(ReloadConfig reloadConfig)
        {
            m_ReloadConfig = reloadConfig;
            m_DispatcherQueue = m_ReloadConfig.DispatcherQueue;
            link.ReloadFLMEventHandler += new ReloadFLMEvent(link_ReloadFLMEventHandler);
        }
Пример #16
0
 private void onInitialized(object sender, EventArgs e)
 {
     taskQueue = new DispatcherQueue("DriveControl", new Dispatcher(1, "DriveControl"),
         TaskExecutionPolicy.ConstrainQueueDepthDiscardTasks, 1);
     Arbiter.Activate(taskQueue, Arbiter.Receive(true, drivePort, driveHandler));
     UpdateJoystickAxes(new game.Axes());
 }
 public HandlerBase(DriveOperationsService service, ccr.DispatcherQueue queue)
     : base(queue)
 {
     _service = service;
 }
Пример #18
0
        public void PortSetReceiveToBeUsedWithIterators()
        {
            iterPort = new PortSet (typeof (string), typeof (char), typeof (int));
            iterEvent = new AutoResetEvent (false);
            iterRes = 0;

            using (Dispatcher d = new Dispatcher ()) {
                var disp = new DispatcherQueue ("bla", d);
                disp.Enqueue (new IterativeTask (this.SimpleTaskIterator));
                for (int i = 0; i < 5; ++i)
                    iterPort.PostUnknownType ((i + 1) * 10);
                Assert.IsTrue (iterEvent.WaitOne (2000), "#1");
                Assert.AreEqual (150, iterRes, "#2");
            }
        }
Пример #19
0
        static void ParallelMul()
        {

            InputData[] ClArr = new InputData[nc];
            for (int i = 0; i < nc; i++)
                ClArr[i] = new InputData();


            int step = (Int32)(m / nc);

            int c = -1;
            for (int i = 0; i < nc; i++)
            {
                ClArr[i].start = c + 1;
                ClArr[i].stop = c + step;
                c = c + step;
            }

            Dispatcher d = new Dispatcher(nc, "Test Pool");
            DispatcherQueue dq = new DispatcherQueue("Test Queue", d);

            Port<int> p = new Port<int>();

            for (int i = 0; i < nc; i++)
                Arbiter.Activate(dq, new Task<InputData, Port<int>>(ClArr[i], p, Mul));

            Arbiter.Activate(dq, Arbiter.MultipleItemReceive(true, p, nc, delegate (int[] array)
            {
  
                Console.WriteLine("Вычисления завершены");
                Console.ReadKey(true);
                Environment.Exit(0);
            }));
        }
Пример #20
0
 internal void Step(ITask task, DispatcherQueue queue)
 {
     try {
         if (iterator.MoveNext ()) {
             task = iterator.Current;
             task.LinkedIterator = this;
             task.TaskQueue = queue;
             task.Execute ();
         }
     }  catch (Exception ex) {
         this.iterator.Dispose ();
         this.iterator = null;
         Console.WriteLine (ex);
         //TODO post it somewhere
     }
 }
Пример #21
0
        static void Main(string[] args)
        {
            int i;
            nc = 2;
            n = 50000;

            Console.WriteLine("\nМассив включает в себя {0} элементов\n", n);

            a = new int[n];
            mem = new int[n];
            b = new int[nc];

            Random r = new Random();
            for (int j = 0; j < n; j++)
                a[j] = r.Next(10000);
            a.CopyTo(mem,0); //запомнили полученный массив
            Console.WriteLine("Исходный массив успешно заполнен случайными значениями!\n");

            arrDisplay();

            System.Diagnostics.Stopwatch sWatch = new System.Diagnostics.Stopwatch();
            Console.WriteLine("Начата последовательная сортировка массива...\n");
            sWatch.Start();
            for (i = 0; i <= n - 1; i++)
            {
                for (int j = i + 1; j < n; j++)
                {
                    if (a[j] < a[i])
                    {
                        var temp = a[i];
                        a[i] = a[j];
                        a[j] = temp;
                    }
                }
            }
            sWatch.Stop();
            Console.WriteLine("Массив отсортирован последовательным алгоритмом!\n");
            Console.WriteLine("Последовательный алгоритм = {0} мс.", sWatch.ElapsedMilliseconds.ToString());

            arrDisplay(); //показали отсортированный массив

            mem.CopyTo(a, 0); ; // восстановили массив со случайными числами 

            // создание массива объектов для хранения параметров 
            InputData[] tempArray = new InputData[nc];
            i = 0;
            while (i < nc)
                {tempArray[i] = new InputData(); i++;}
            // делим количество элементов  в массиве на nc частей 
            int step = (Int32)(n / nc);
            // заполняем массив параметров 
            int c = -1;
            for (i = 0; i < nc; i++)
            {
                tempArray[i].start = c + 1;
                tempArray[i].stop = c + step;
                c = c + step;
            }
            Dispatcher d = new Dispatcher(nc, "Test Pool");
            DispatcherQueue dq = new DispatcherQueue("Test Queue", d);
            Port<int> p = new Port<int>();


            for (i = 0; i < nc; i++)
                Arbiter.Activate(dq, new Task<InputData, Port<int>>(tempArray[i], p, Mul));

            Console.WriteLine("Начата параллельная сортировка массива...\n");
            Arbiter.Activate(dq, Arbiter.MultipleItemReceive(true, p, nc, delegate(int[] array)
     {
         Console.WriteLine("Массив отсортирован параллельным алгоритмом!\n");
         System.Diagnostics.Stopwatch newWatch = new System.Diagnostics.Stopwatch();
         Console.WriteLine("Начата последовательная сортировка массива...\n");
         newWatch.Start();
         Array.Sort(a); //тот самый делегат в приемнике, с помощью которого шлейфуется результат параллельной сортировки пузырьком
         newWatch.Stop();
         Console.WriteLine("Окончательная сортировка средтвами C#: {0} мс.\n", newWatch.ElapsedMilliseconds.ToString());
         arrDisplay();
         Console.WriteLine("Вычисления завершены");
         Console.ReadKey(true);
         Environment.Exit(0);
     }));

        }
Пример #22
0
		private void SetupOutMessagesOnRelayThreads(RelayNodeConfig newConfiguration) 
		{
			//if it was off and is now on, or if it was on and the number of threads changed
			bool setupNewOutMessages = (newConfiguration.OutMessagesOnRelayThreads && configuration.OutMessagesOnRelayThreads == false)
			                           || (configuration.OutMessagesOnRelayThreads && newConfiguration.OutMessagesOnRelayThreads
			                               && newConfiguration.NumberOfOutMessageThreads != configuration.NumberOfOutMessageThreads);

			Dispatcher oldOutDispatcher = outDispatcher;
			DispatcherQueue oldOutMessageQueue = outMessageQueue;

			if (setupNewOutMessages)
			{
				try
				{
					const string outThreadsName = "DataRelayNodeOUT";
						
					outMessagePort = new Port<RelayMessageAsyncResult>(); //atomic
					outMessagesPort = new Port<RelayMessageListAsyncResult>(); //atomic

					if (newConfiguration.NumberOfOutMessageThreads > 0)
					{
						outDispatcher = new Dispatcher(newConfiguration.NumberOfOutMessageThreads, ThreadPriority.Normal, true, outThreadsName);
					}
					else
					{
						outDispatcher = new Dispatcher { Name = outThreadsName };
					}

					outMessageQueue = new DispatcherQueue("DataRelayDispatcherQueueOUT", outDispatcher, TaskExecutionPolicy.ConstrainQueueDepthThrottleExecution, newConfiguration.MaximumOutMessageQueueDepth);

					Arbiter.Activate(outMessageQueue,
									 Arbiter.ReceiveWithIterator(true, outMessagePort, HandleOutMessage));
					Arbiter.Activate(outMessageQueue,
									 Arbiter.ReceiveWithIterator(true, outMessagesPort, HandleOutMessages));
						
				}
				catch (Exception e)
				{	
                    if(log.IsErrorEnabled)
                        log.ErrorFormat("Error setting up Out Message Threads on RelayNode: {0}", e);                    
					throw;
				}
			}

			if (newConfiguration.OutMessagesOnRelayThreads == false)
			{
				outMessagePort = null;
				outMessagesPort = null;
				if (oldOutDispatcher != null) oldOutDispatcher.Dispose();
				if (oldOutMessageQueue != null) oldOutMessageQueue.Dispose();
			}
		}
            ///////////////////////////////////////////////////////////////////
            // __use__.snippet0.snippet.noop - [(__use__.snippet0.snippet.expr1 - __use__.snippet0.snippet.join)(__use__.snippet0.snippet.expr0 - &__use__.snippet0.snippet.join)(__use__.snippet0.snippet.expr - &__use__.snippet0.snippet.join)] - __use__.snippet0.call - __use__.snippet0.call.iftype
            // __use__0.snippet.call - __use__0.snippet.call.iftype
            // [(snippet.snippet.noop - snippet.snippet.expr - snippet.snippet.join)] - snippet.element
            ///////////////////////////////////////////////////////////////////

            public RotateMessageHandler(DriveOperationsService service, ccr.DispatcherQueue queue)
                : base(service, queue)
            {
            }
Пример #24
0
 internal void Register(DispatcherQueue queue)
 {
     lock (_lock) {
         DispatcherQueue[] res = new DispatcherQueue [queues.Length + 1];
         queues.CopyTo (res, 0);
         res [queues.Length] = queue;
         queues = res;
     }
 }
Пример #25
0
 public HandlerBase(DiagramService service, ccr.DispatcherQueue queue)
     : base(queue)
 {
     _service = service;
 }
Пример #26
0
        static void paral_qsort(int[] a, int left, int right)
        {
            int l = left;
            int r = right;
            int val = 0;
            int mid = a[(l + r) / 2];

            while (l <= r)
            {
                while ((a[l] < mid) && (l <= right))
                {
                    l++;
                }
                while ((a[r] > mid) && (r >= left))
                {
                    r--;
                }

                if (l <= r)
                {
                    val = a[l];
                    a[l] = a[r];
                    a[r] = val;
                    l++;
                    r--;
                }
            }

            InputData data1 = new InputData();
            InputData data2 = new InputData();

            if (r > left)
            {
                data1.str="Нить исполнения 1";
                data1.array = a; data1.start = left; data1.stop = r;
                //qsort(a, left, r);
            }
            if (l < right)
            {
                data2.str = "Нить исполнения 2";
                data2.array = a; data2.start = l; data2.stop = right;
                //qsort(a, l, right);
            }

            //Создаём диспетчеры
            Dispatcher d = new Dispatcher(2, " Test Pool");
            DispatcherQueue dq = new DispatcherQueue(" Test Queue", d);

            //Описываем порт
            Port<int> p = new Port<int>();

            Arbiter.Activate(dq, new Task<InputData, Port<int>>(data1, p, thread_fun));
            Arbiter.Activate(dq, new Task<InputData, Port<int>>(data2, p, thread_fun));

            return;
        }
Пример #27
0
        internal void PostInternal(bool insertAtHead, PortElement <T> node)
        {
            bool            flag            = false;
            ITask           task            = null;
            DispatcherQueue dispatcherQueue = null;

            lock (Store)
            {
                if (insertAtHead)
                {
                    Store.ElementListAddFirst(node);
                }
                else
                {
                    Store.ElementListAddLast(node);
                }
                if (Store.ReceiverCount == 0)
                {
                    return;
                }
                int num = 1;
                if (Store.ActiveReceiver == null)
                {
                    num = Store.ReceiverCount;
                }
                ReceiverTask receiverTask = Store.ActiveReceiver;
                int          i            = 0;
                while (i < num)
                {
                    if (num != 1)
                    {
                        receiverTask = Store.GetReceiverAtIndex(i);
                    }
                    task            = null;
                    flag            = receiverTask.Evaluate(node, ref task);
                    dispatcherQueue = receiverTask.TaskQueue;
                    if (flag)
                    {
                        Store.ElementListRemove(node);
                        if (receiverTask.State != ReceiverTaskState.Persistent)
                        {
                            Store.RemoveReceiver(receiverTask);
                            if (i > 1)
                            {
                                i--;
                            }
                            else
                            {
                                receiverTask = Store.ActiveReceiver;
                            }
                            num = Store.ReceiverCount;
                            break;
                        }
                        break;
                    }
                    else
                    {
                        if (task != null)
                        {
                            dispatcherQueue.Enqueue(task);
                        }
                        i++;
                    }
                }
            }
            if (flag && task != null)
            {
                dispatcherQueue.Enqueue(task);
            }
        }
Пример #28
0
            ///////////////////////////////////////////////////////////////////
            // __use__30.snippet0.snippet.noop - __use__30.snippet0.snippet.expr - __use__30.snippet0.snippet.join
            // __use__30.snippet0.call - __use__30.snippet0.call.iftype
            ///////////////////////////////////////////////////////////////////

            public OnWaitForDriveCompletionReplaceHandler(DiagramService service, ccr.DispatcherQueue queue)
                : base(service, queue)
            {
                RegisterAndActivateJoins();
            }
Пример #29
0
        /// <summary>
        /// Initialize the control and start the Python engine.  This is not in the constructor or
        /// OnLoaded because it breaks the VS designer.  The main GUI window calls this.
        /// </summary>
        public void StartScripting()
        {
            pe = new PythonEngine();
            pe.Sys.path.Add(Myro.Utilities.Params.BinPath);
            //pe.Sys.path.Add(Myro.Utilities.Params.PythonPath);
            //pe.Sys.path.Add("C:\\Users\\t-richr\\Myro-dev\\richard-dev-2\\Frontend\\Python");
            //pe.Import("site");
            pe.Sys.path.Add(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location));

            var s = new AnonymousPipeServerStream(PipeDirection.In);
            stdout = s;
            stdoutpipe = new AnonymousPipeClientStream(PipeDirection.Out, s.ClientSafePipeHandle);
            readThreadOut = new Thread(new ThreadStart(delegate() { readLoop(stdout, Colors.Black); }));
            readThreadOut.Start();

            var e = new AnonymousPipeServerStream(PipeDirection.In);
            stderr = e;
            stderrpipe = new AnonymousPipeClientStream(PipeDirection.Out, e.ClientSafePipeHandle);
            readThreadErr = new Thread(new ThreadStart(delegate() { readLoop(stderr, Colors.Crimson); }));
            readThreadErr.Start();

            commandQueue = new Port<Command>();
            commandDispatcherQueue = new DispatcherQueue("Python command queue", new Dispatcher(1, "Python command queue"));
            Arbiter.Activate(commandDispatcherQueue, Arbiter.Receive(true, commandQueue, commandHandler));

            pe.SetStandardOutput(stdoutpipe);
            pe.SetStandardError(stderrpipe);
            //Console.SetOut(new StreamWriter(stdoutpipe));
            //Console.SetError(new StreamWriter(stderrpipe));

            //Console.OpenStandardOutput();
            //Console.OpenStandardError();

            historyBlock.Document.PageWidth = historyBlock.ViewportWidth;
            historyBlock.Document.Blocks.Clear();
            paragraph = new Paragraph();
            historyBlock.Document.Blocks.Add(paragraph);
            historyBlock.IsEnabled = true;
        }
Пример #30
0
		internal void ReloadConfig(RelayNodeConfig newConfiguration)
		{
			if (newConfiguration != null)
			{
                if (log.IsInfoEnabled)
                    log.Info("Reloading configs.");

				fatalFailureTimeout = newConfiguration.FatalShutdownTimeout < 0
					? TimeSpan.FromMinutes(5)
					: TimeSpan.FromSeconds(newConfiguration.FatalShutdownTimeout);

				if (newConfiguration.GetMyNode() != null)
				{
					MyZone = newConfiguration.GetMyNode().Zone;
				}

				SetClusterAddresses(newConfiguration);
				
				messageTracer.ReloadConfig(newConfiguration.TypeSettings.MaxTypeId, newConfiguration.TraceSettings);
				messageTracer.Activated = newConfiguration.OutputTraceInfo;

				//TODO: handle changes in component definition
				components.ReloadConfig(newConfiguration, newConfiguration.IgnoredMessageTypes);

				if (newConfiguration.TransportSettings != null)  
				{
                    if(newConfiguration.TransportSettings.ListenPort != portNumber)
                    {
                    	log.InfoFormat("Changing Socket Transport Port to {0}",
                    		               newConfiguration.TransportSettings.ListenPort);
                    	portNumber = newConfiguration.TransportSettings.ListenPort;
                    	SocketServerAdapter.ChangePort(portNumber);
                    }
					if(newConfiguration.TransportSettings.HttpListenPort != httpPortNumber)
					{
						if (httpPortNumber < 1 && newConfiguration.TransportSettings.HttpListenPort > 0) //there was no http server and now we want one
						{
							httpPortNumber = newConfiguration.TransportSettings.HttpListenPort;
							StartHttpServer();

						}
						else if (newConfiguration.TransportSettings.HttpListenPort < 1 && httpPortNumber > 0) //shut off a running server
						{
							httpPortNumber = newConfiguration.TransportSettings.HttpListenPort;
							StopHttpServer();
						}
						else //just change the port on an existing server
						{
							log.InfoFormat("Changing Http Transport Port to {0}",
											   newConfiguration.TransportSettings.HttpListenPort);
							httpPortNumber = newConfiguration.TransportSettings.HttpListenPort;
							_httpServer.ChangePort(httpPortNumber);	
						}
						
					}
				}

				if (newConfiguration.NumberOfThreads != configuration.NumberOfThreads)
				{
					if(log.IsInfoEnabled)
                        log.InfoFormat("Changing number of relay node threads from {0} to {1}", 
                            configuration.NumberOfThreads, newConfiguration.NumberOfThreads);
					try
					{
						Dispatcher oldInDispatcher = inDispatcher;
						Dispatcher newInDispatcher;
						const string inThreadsName = "DataRelayNode";
						if (newConfiguration.NumberOfThreads > 0)
						{
							newInDispatcher = new Dispatcher(newConfiguration.NumberOfThreads, ThreadPriority.Normal, true, inThreadsName);
						}
						else
						{
							newInDispatcher = new Dispatcher() { Name = inThreadsName };
						}

						DispatcherQueue newInQueue = new DispatcherQueue("DataRelayDispatcherQueue", newInDispatcher, TaskExecutionPolicy.ConstrainQueueDepthThrottleExecution, newConfiguration.MaximumMessageQueueDepth);

						Interlocked.Exchange(ref inMessagePort, new Port<RelayMessage>());
						Interlocked.Exchange(ref inMessageWithContextPort, new Port<RelayMessageWithContext>());
						Interlocked.Exchange(ref inMessagesPort, new Port<IList<RelayMessage>>());

						Arbiter.Activate(newInQueue,
							 Arbiter.Receive<RelayMessage>(true, inMessagePort, HandleInMessage));
						Arbiter.Activate(newInQueue,
							 Arbiter.Receive<RelayMessageWithContext>(true, inMessageWithContextPort, HandleInMessage));
						Arbiter.Activate(newInQueue,
							 Arbiter.Receive<IList<RelayMessage>>(true, inMessagesPort, HandleInMessages));

						inMessageQueue = newInQueue;
						inDispatcher = newInDispatcher;
						oldInDispatcher.Dispose();
					}
					catch (Exception e)
					{
                        if (log.IsErrorEnabled)
                            log.ErrorFormat("Error changing number of relay node threads: {0}", e);
					}
				}
				else
				{
					//not rebuilding the queue, but reset its max queue depth anyway
					inMessageQueue.MaximumQueueDepth = newConfiguration.MaximumMessageQueueDepth;
				}

				SetupOutMessagesOnRelayThreads(newConfiguration);

				queuedTaskThreshold = (int)Math.Floor(0.9 * newConfiguration.MaximumMessageQueueDepth);
				configuration = newConfiguration;
                if (log.IsInfoEnabled)
                    log.Info("Done Reloading configs.");
			}
			else
			{
                if (log.IsErrorEnabled)
                    log.Error("Attempt to reload null config");
			}
		}
Пример #31
0
 protected CcrServiceBase(DispatcherQueue dispatcherQueue) : this()
 {
     this.dispatcherQueue = dispatcherQueue;
 }
Пример #32
0
		/// <summary>
		/// Initializes the <see cref="RelayNode"/> with the given <see cref="ComponentRunState"/>s,
		/// must be called before calling <see cref="Start"/>
		/// </summary>
		/// <param name="componentRunStates"></param>
		public void Initialize(ComponentRunState[] componentRunStates)
		{
			try
			{
                if (log.IsInfoEnabled)
                {
                    if (componentRunStates == null)
                    {
                        log.Info("Initializing Relay Node.");
                    }
                    else
                    {
                        log.Info("Initialzing Relay Node with Component Run States.");
                    }
                }

				EnvironmentManager.EnvironmentChanged += EnvironmentChangedHandler;

                GetConfig();
				
				if (configuration == null) throw new ConfigurationErrorsException("config failed to load, is null");

				SetClusterAddresses(configuration);

				fatalFailureTimeout = configuration.FatalShutdownTimeout < 0
					? TimeSpan.FromMinutes(5)
					: TimeSpan.FromSeconds(configuration.FatalShutdownTimeout);

				components = new RelayComponents(configuration);

				if (configuration != null)
				{
					messageTracer = new MessageTracer(configuration.TypeSettings.MaxTypeId, configuration.TraceSettings);
					messageTracer.Activated = configuration.OutputTraceInfo;

					const string inThreadsName = "DataRelayNode";
					if (configuration.NumberOfThreads > 0)
					{
						inDispatcher = new Dispatcher(configuration.NumberOfThreads, ThreadPriority.Normal, true, inThreadsName);
					}
					else
					{
						inDispatcher = new Dispatcher() { Name = inThreadsName } ;
					}

					const string outThreadsName = "DataRelayNodeOUT";
					if (configuration.OutMessagesOnRelayThreads)
					{
						if (configuration.NumberOfOutMessageThreads > 0)
						{
							outDispatcher = new Dispatcher(configuration.NumberOfOutMessageThreads, ThreadPriority.Normal, true, outThreadsName);
						}
						else
						{
							outDispatcher = new Dispatcher { Name = outThreadsName };
						}

						outMessagePort = new Port<RelayMessageAsyncResult>();
						outMessagesPort = new Port<RelayMessageListAsyncResult>();

						outMessageQueue = new DispatcherQueue("DataRelayDispatcherQueueOUT", outDispatcher, TaskExecutionPolicy.ConstrainQueueDepthThrottleExecution, configuration.MaximumOutMessageQueueDepth);
						Arbiter.Activate(outMessageQueue,
								Arbiter.ReceiveWithIterator(true, outMessagePort, HandleOutMessage));
						Arbiter.Activate(outMessageQueue,
								Arbiter.ReceiveWithIterator(true, outMessagesPort, HandleOutMessages));
					}

					inMessageQueue = new DispatcherQueue("DataRelayDispatcherQueue", inDispatcher, TaskExecutionPolicy.ConstrainQueueDepthThrottleExecution, configuration.MaximumMessageQueueDepth);
					
					queuedTaskThreshold = (int)Math.Floor(0.9 * configuration.MaximumMessageQueueDepth);
					
					
					// setup RelayServicesClient before initalizing components
					RelayServicesClient.Instance.RelayNodeServices = this;
					
					Arbiter.Activate(inMessageQueue,
						Arbiter.Receive<RelayMessage>(true, inMessagePort, HandleInMessage));
					Arbiter.Activate(inMessageQueue,
								Arbiter.Receive<RelayMessageWithContext>(true, inMessageWithContextPort, HandleInMessage));
					Arbiter.Activate(inMessageQueue,
								Arbiter.Receive<IList<RelayMessage>>(true, inMessagesPort, HandleInMessages));
					

					//by having after the Arbiter.Activate it allows Initialize components to use 
					//IRelayNodeServices that require Message handling
					components.Initialize(componentRunStates, configuration.IgnoredMessageTypes);

					queuedMessageCounterTimer = new Timer(CountQueuedMessages, null, 5000, 5000);
				}
			}
			catch (Exception ex)
			{
                if (log.IsErrorEnabled)
                    log.ErrorFormat("Exception initializing relay node: {0}", ex);
				throw; //should bring server down
			}
		}
Пример #33
0
            static void Main(string[] args)
        {
            int i;
            nc = 2;
            n = 100000000;
            a = new int[n];
            b = new int[nc];

            Random r = new Random();
            for (int j = 0; j < n; j++)
                a[j] = r.Next(100);
            System.Diagnostics.Stopwatch sWatch = new System.Diagnostics.Stopwatch();
            sWatch.Start();
            for (i = 0; i <= n; i++)
            {
                for (int j = i; i <= n; i++)
                {
                    if (a[j] > a[j + 1])
                    {
                        int e = a[j]; //change for elements
                        a[j] = a[j + 1];
                        a[j + 1] = e;
                    }
                }
            }
            sWatch.Stop();
            Console.WriteLine("Последовательный алгоритм = {0} мс.", sWatch.ElapsedMilliseconds.ToString());
            
            // создание массива объектов для хранения параметров 
            InputData[] ClArr = new InputData[nc];
            for (i = 0; i < nc; i++)
                ClArr[i] = new InputData();
            // делим количество элементов  в массиве на nc частей 
            int step = (Int32)(n / nc);
            // заполняем массив параметров 
            int c = -1;
            for (i = 0; i < nc; i++)
            {
                ClArr[i].start = c + 1;
                ClArr[i].stop = c + step;
                ClArr[i].i = i;
                c = c + step;
            }
            Dispatcher d = new Dispatcher(nc, "Test Pool");
            DispatcherQueue dq = new DispatcherQueue("Test Queue", d);
            Port<int> p = new Port<int>();                
            for (i = 0; i < nc; i++)
                Arbiter.Activate(dq, new Task<InputData, Port<int>>(ClArr[i], p, Mul));

            Arbiter.Activate(dq, Arbiter.MultipleItemReceive(true, p, nc, delegate(int[] array)
     {   }));
        }
Пример #34
0
        public void ParallelShell()
        {
            processes = new InputData[nc];
            Console.WriteLine("Параллельная сортировка");
            //Console.WriteLine("Массив до сортировки:");
            //Display(0, partSize * nc);

            int c = -1;
            for (int i = 0; i < nc; i++)
            {
                processes[i] = new InputData();
                processes[i].start = c + 1;
                processes[i].stop = c + partSize - 1;
                c += partSize - 1;
            }

             dq = new DispatcherQueue("Queue", d);
             p1 = new Port<int>();


            for (int i = 0; i < nc; i++)
            {
                Arbiter.Activate(dq, new Task<InputData, Port<int>>(processes[i], p1, FirstPhase));
            }

            // Все потоки завершили работу, финальная сортировка
            Arbiter.Activate(dq, Arbiter.MultipleItemReceive(true, p1, nc, delegate(int[] array)
            {
                Stopwatch sw = new Stopwatch();

                Console.WriteLine("Финальная сортировка");
                sw.Start();
                

                //int inner, temp;

                //for (int i = 0; i < partSize * nc; i++)
                //{
                //    temp = dataArray[i];
                //    inner = i;

                //    while (inner > 0 && dataArray[inner - 1] >= temp)
                //    {
                //        dataArray[inner] = dataArray[inner - 1];
                //        inner--;
                //    }
                //    dataArray[inner] = temp;
                //}
                Array.Sort(dataArray);
                sw.Stop();
                Console.WriteLine("Финальная сортировка заняла {0} мс", sw.ElapsedMilliseconds.ToString());
                //Console.WriteLine("Результат:");
                //Display(0, nc * partSize);
            
            }
        ));
        }
Пример #35
0
 public static void ExecuteNow(DispatcherQueue dispatcherQueue, ITask task)
 {
     task.TaskQueue = dispatcherQueue;
     TaskExecutionWorker.ExecuteInCurrentThreadContext(task);
 }
Пример #36
0
            ///////////////////////////////////////////////////////////////////
            // program.activity.Start+start
            // snippet.element
            // __use__.snippet0.call - __use__.snippet0.call.iftype
            // [(__use__0.snippet0.snippet.noop - __use__0.snippet0.snippet.expr - __use__0.snippet0.snippet.join)] - __use__0.snippet0.call - __use__0.snippet0.call.iftype
            ///////////////////////////////////////////////////////////////////

            public StartHandler(DiagramService service, ccr.DispatcherQueue queue)
                : base(service, queue)
            {
            }
Пример #37
0
        internal ITask Dequeue(ref int start, out DispatcherQueue queue)
        {
            DispatcherQueue[] queues = this.queues;
            ITask task  = null;
            int qlen = queues.Length;

            while (active) {
                for (int i = 0; i < qlen; ++i) {
                    int idx = (i + start) % qlen;
                    if (queues [idx].TryDequeue (out task)) {
                        queue = queues [idx];
                        start = (idx + 1) % qlen;
                        Interlocked.Decrement (ref pendingTasks);
                        return task;
                    }
                }

                lock (_lock) {
                    for (int i = 0; i < qlen; ++i) {
                        int idx = (i + start) % qlen;
                        if (queues [idx].TryDequeue (out task)) {
                            queue = queues [idx];
                            start = (idx + 1) % qlen;
                            Interlocked.Decrement (ref pendingTasks);
                            return task;
                        }
                    }
                    Interlocked.Increment (ref pendingWorkers);
                    Monitor.Wait (_lock);
                    Interlocked.Decrement (ref pendingWorkers);
                }
            }
            queue = null;
            return null;
        }
Пример #38
0
        /// <summary>
        /// Start conversation with the SickLRF device.
        /// </summary>
        IEnumerator<ITask> StartLRF(int timeout, int comPort)
        {
            Tracer.Trace("SickLRF::StartLRF() comPort=" + comPort);

            if (timeout > 0)
            {
                //
                // caller asked us to wait <timeout> milliseconds until we start.
                //

                yield return Arbiter.Receive(false, TimeoutPort(timeout),
                    delegate(DateTime dt)
                    {
                        LogInfo("Done Waiting");
                    }
                );
            }

            if (_queue == null)
            {
                //
                // The internal services run on their own dispatcher, we need to create that (once)
                //

                AllocateExecutionResource allocExecRes = new AllocateExecutionResource(0, "SickLRF");

                ResourceManagerPort.Post(allocExecRes);

                yield return Arbiter.Choice(
                    allocExecRes.Result,
                    delegate(ExecutionAllocationResult result)
                    {
                        _queue = result.TaskQueue;
                    },
                    delegate(Exception e)
                    {
                        LogError(e);
                    }
                );
            }

            string comName;

            if (comPort <= 0)
            {
                //
                // We default to COM4, because
                // a) that was our previous behavior and
                // b) the hardware that we have uses COM4
                //
                comName = "COM4";
            }
            else
            {
                comName = "COM" + comPort;
            }

            _link = new CommLink(_queue ?? TaskQueue, comName, _internalPort);
            _link.Parent = ServiceInfo.Service;
            _link.Console = ConsoleOutputPort;

            FlushPortSet(_internalPort);
            yield return(
                Arbiter.Choice(
                    _link.Open(),
                    delegate(SuccessResult success)
                    {
                        LogInfo("Opened link to LRF");
                    },
                    delegate(Exception exception)
                    {
                        LogError(exception);
                    }
                )
            );
        }
Пример #39
0
        internal void Notify(DispatcherQueue queue)
        {
            int curPending = Interlocked.Increment (ref pendingTasks);

            if (workers.Count == 0 || (curPending > 0 && workers.Count < maxThreads)) {
                SpawnWorker ();
                return;
            }

            lock (_lock) {
                if (Thread.VolatileRead (ref pendingWorkers) != 0)
                    Monitor.Pulse (_lock);
            }
        }