public Select ( [ items, int itemsCount, long timeout ) : bool | ||
items | [ | Items to select on (must not be null) |
itemsCount | int | Number of items in the array to select on |
timeout | long | a time-out period, in milliseconds |
return | bool |
public PollEvents Poll(PollEvents pollEvents, TimeSpan timeout) { NetMQSelector.Item[] items = { new NetMQSelector.Item(this, pollEvents) }; m_netMqSelector.Select(items, 1, (long)timeout.TotalMilliseconds); return(items[0].ResultEvent); }
/// <summary> /// Runs the poller on the caller's thread. Only returns when <see cref="Stop"/> or <see cref="StopAsync"/> are called from another thread. /// </summary> private void RunPoller() { try { // Recalculate all timers now foreach (var timer in m_timers) { if (timer.Enable) { timer.When = Clock.NowMs() + timer.Interval; } } // Run until stop is requested while (!m_stopSignaler.IsStopRequested) { if (m_isPollSetDirty) { RebuildPollset(); } var pollStart = Clock.NowMs(); // Set tickless to "infinity" long tickless = pollStart + int.MaxValue; // Find the When-value of the earliest timer.. foreach (var timer in m_timers) { // If it is enabled but no When is set yet, if (timer.When == -1 && timer.Enable) { // Set this timer's When to now plus it's Interval. timer.When = pollStart + timer.Interval; } // If it has a When and that is earlier than the earliest found thus far, if (timer.When != -1 && tickless > timer.When) { // save that value. tickless = timer.When; } } // Compute a timeout value - how many milliseconds from now that the earliest-timer will expire. var timeout = tickless - pollStart; // Use zero to indicate it has already expired. if (timeout < 0) { timeout = 0; } var isItemAvailable = false; if (m_pollSet.Length != 0) { isItemAvailable = m_netMqSelector.Select(m_pollSet, m_pollSet.Length, timeout); } else if (timeout > 0) { //TODO: Do we really want to simply sleep and return, doing nothing during this interval? //TODO: Should a large value be passed it will sleep for a month literally. // Solution should be different, but sleep is more natural here than in selector (timers are not selector concern). Debug.Assert(timeout <= int.MaxValue); Thread.Sleep((int)timeout); } // Get the expected end time in case we time out. This looks redundant but, unfortunately, // it happens that Poll takes slightly less than the requested time and 'Clock.NowMs() >= timer.When' // may not true, even if it is supposed to be. In other words, even when Poll times out, it happens // that 'Clock.NowMs() < pollStart + timeout' var expectedPollEnd = !isItemAvailable ? pollStart + timeout : -1L; // that way we make sure we can continue the loop if new timers are added. // timers cannot be removed foreach (var timer in m_timers) { if ((Clock.NowMs() >= timer.When || expectedPollEnd >= timer.When) && timer.When != -1) { timer.InvokeElapsed(this); if (timer.Enable) { timer.When = Clock.NowMs() + timer.Interval; } } } for (var i = 0; i < m_pollSet.Length; i++) { NetMQSelector.Item item = m_pollSet[i]; if (item.Socket != null) { NetMQSocket socket = m_pollact[i]; if (item.ResultEvent.HasError()) { if (++socket.Errors > 1) { Remove(socket); item.ResultEvent = PollEvents.None; } } else { socket.Errors = 0; } if (item.ResultEvent != PollEvents.None) { socket.InvokeEvents(this, item.ResultEvent); } } else if (item.ResultEvent.HasError() || item.ResultEvent.HasIn()) { if (m_pollinSockets.TryGetValue(item.FileDescriptor, out Action <Socket> action)) { action(item.FileDescriptor); } } } } #if !NET35 // Try to dequeue and execute all pending tasks before stopping poller while (m_tasksQueue.TryDequeue(out Task task, TimeSpan.Zero)) { TryExecuteTask(task); } #endif } finally { foreach (var socket in m_sockets.ToList()) { Remove(socket); } } }