// Reads incoming data from the client's network stream private void Read() { // Get client stream // TODO - this can fail if internet drops, needs to be debugged and checked for var Stream = Client.GetStream(); // Create a byte buffer int BytesRead = Client.Available; byte[] Buffer = new byte[BytesRead]; // Create a wait handle array so we can cancel this thread if need be Stream.BeginRead(Buffer, 0, BytesRead, (IAsyncResult Result) => { try { // Check if peer has been stopped if (StopEvent.WaitOne(0)) return; // End reading BytesRead = Stream.EndRead(Result); // Check if any data was read if (BytesRead > 0) { // Invoke data received handler Server.OnDataReceived?.Invoke((this, Buffer), EventArgs.Empty); }
// Reads incoming data from the client's network stream private void Read() { // Get client stream var Stream = Client.GetStream(); // Create a byte buffer byte[] Buffer = new byte[Client.Available]; // Create a wait handle array so we can cancel this thread if need be Stream.BeginRead(Buffer, 0, Client.Available, (IAsyncResult Result) => { try { // Check if peer has been stopped if (StopEvent.WaitOne(0)) { return; } // End reading var BytesRead = Stream.EndRead(Result); // Check if any data was read if (BytesRead > 0) { // Invoke data received handler Server.OnDataReceived?.Invoke((this, Buffer), EventArgs.Empty); }
/// <summary> /// Signals the service to stop. /// </summary> public void Stop() { if (StopEvent.WaitOne(0)) { throw new InvalidOperationException("Service is already stopped, or is running in an unsupported mode."); } StopEvent.Set(); }
private void ProcessItem(MailQueueItem item) { //Console.WriteLine("Start ProcessItem({0})", item.Account.Account); // The following code prevents current task from starting if service is stopped. if (StopEvent.WaitOne(0)) { return; } item.Retrieve(_collector.ItemsPerSession, StopEvent); }
protected override WorkItem <MailQueueItem> Selector() { // The following block stops generating tasks if service is stopped. if (StopEvent.WaitOne(0)) { return(null); } MailQueueItem item = _collector.GetItem(); return(item != null ? new WorkItem <MailQueueItem>(item) : null); }
private async Task ProcessQueue(Stream stream) { while (true) { await Task.WhenAny(DataAvailableEvent.WaitOneAsync(), StopEvent.WaitOneAsync()); if (!StopEvent.WaitOne(0)) { byte[] data; if (!DataQueue.TryDequeue(out data)) { Logger.Trace("Unable to deque element from Queue due to concurrency access"); } if (DataQueue.IsEmpty) { Logger.Trace("Writing queue is empty. Wait for new element..."); DataAvailableEvent.Reset(); } try { Logger.Trace("Write queue element {0}", data.GetHashCode()); await stream.WriteAsync(data, 0, data.Length); } catch (Exception e) { Logger.Debug(e, "Unable to send data"); QueueData(data); break; } } else { Logger.Trace("Queue is stopped"); StopEvent.Reset(); break; } } }
// Accepts incoming connections if we are able private void AcceptPeerConnection() { // Create a wait handle array so we can cancel this thread if need be WaitHandle[] Wait = new[] { ReadyEvent, StopEvent }; while (0 == WaitHandle.WaitAny(Wait)) { // Check if stopped if (StopEvent.WaitOne(0)) { break; } // Lock our connection queue to prevent any race conditions lock (ConnectionQueue) { // Connection queue has entries, accept one if (ConnectionQueue.Count > 0) { // Dequeue the new peer in line var Connection = ConnectionQueue.Dequeue(); // Create a peer instance var Peer = new P2pPeer(this, Connection, PeerDirection.IN); // Handle this connection AddPeer(Peer); } // There are no entries in the connection queue else { // No peers in line, reset ready event ReadyEvent.Reset(); continue; } } } }
// Writes a log message to the console, as well as to an optional log file // TODO - this is kind of a monolith, it could probably be shortened private void Write() { // Create a wait handle array so we can cancel this thread if need be WaitHandle[] Wait = new[] { ReadyEvent, StopEvent }; while (0 == WaitHandle.WaitAny(Wait)) { // Check if we need to stop and ignore queue if (StopEvent.WaitOne(0) && IgnoreQueue) { break; } // Lock the message queue to prevent race conditions lock (MessageQueue) { // Check if there are any messages in the queue if (MessageQueue.Count == 0) { ReadyEvent.Reset(); continue; } // Dequeue a message var Message = MessageQueue.Dequeue(); // Check if logging is enabled if (LogLevel <= LogLevel.NONE) { // Reset ready event ReadyEvent.Reset(); continue; } // Create an output string builder StringBuilder Output = new StringBuilder(Message.Message); // Add time and label prefix StringBuilder Prefix = new StringBuilder(""); if (Message.Prefix) { // Add time if (LogLevel >= LogLevel.MAX) { Prefix.Append($"{Message.Timestamp.ToString("dd-MM-yyyy hh:mm:ss.ffffff")} ["); } else if (LogLevel >= LogLevel.DEBUG) { Prefix.Append($"{Message.Timestamp.ToString("dd-MM-yyyy hh:mm:ss.ff")} ["); } else { Prefix.Append($"{Message.Timestamp.ToString("dd-MM-yyyy hh:mm:ss")} ["); } // Add custom prefix if (!string.IsNullOrEmpty(CustomPrefix)) { Prefix.Append($"{CustomPrefix} "); } // Add label if (Message.Label != LogLabel.IMPORTANT) { Prefix.Append($"{Message.Label}]"); } else { Prefix.Append($"{LogLabel.INFO}]"); } // Pad prefix if (LogLevel >= LogLevel.MAX) { Prefix.Append(' ', 37 - Prefix.Length); } else if (LogLevel >= LogLevel.DEBUG) { Prefix.Append(' ', 33 - Prefix.Length); } else { Prefix.Append(' ', 30 - Prefix.Length); } if (!string.IsNullOrEmpty(CustomPrefix)) { Prefix.Append(' '); } } Output.Insert(0, Prefix); // Set console color switch (Message.Label) { case LogLabel.IMPORTANT: Console.ForegroundColor = ImportantColor; break; case LogLabel.INFO: Console.ForegroundColor = InfoColor; break; case LogLabel.ERROR: Console.ForegroundColor = ErrorColor; break; case LogLabel.WARNING: Console.ForegroundColor = WarningColor; break; case LogLabel.DEBUG: Console.ForegroundColor = DebugColor; break; } // Write to console Console.WriteLine(Output); // Append to log file if (!string.IsNullOrEmpty(LogFile)) { try { File.AppendAllText(LogFile, $"{Output}\n"); } catch { } } // Set console color back to default Console.ForegroundColor = ConsoleColor.Gray; } } }
/// <summary> /// Start the service, autodetecting between Windows service and command line. Always blocks until service is stopped. /// </summary> public void Run(ServiceArguments argumentsOverride = null) { ServiceStoppedEvent = new TaskCompletionSource <object>(); Arguments = argumentsOverride ?? new ServiceArguments(Environment.GetCommandLineArgs().Skip(1).ToArray()); CurrentApplicationInfo.Init(ServiceName, Arguments.InstanceName, InfraVersion); if (Arguments.ProcessorAffinity != null) { int processorAffinityMask = 0; foreach (var cpuId in Arguments.ProcessorAffinity) { processorAffinityMask |= 1 << cpuId; } Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(processorAffinityMask); } if (Arguments.ServiceStartupMode == ServiceStartupMode.WindowsService) { Trace.WriteLine("Service starting as a Windows service..."); WindowsService = new DelegatingServiceBase(ServiceName, OnWindowsServiceStart, OnWindowsServiceStop); if (argumentsOverride == null) { Arguments = null; // Ensures OnWindowsServiceStart reloads parameters passed from Windows Service Manager. } ServiceBase.Run(WindowsService); // This calls OnWindowsServiceStart() on a different thread and blocks until the service stops. } else { if (Arguments.ShutdownWhenPidExits != null) { try { MonitoredShutdownProcess = Process.GetProcessById(Arguments.ShutdownWhenPidExits.Value); } catch (ArgumentException e) { Console.WriteLine($"Service cannot start because monitored PID {Arguments.ShutdownWhenPidExits} is not running. Exception: {e}"); Environment.ExitCode = 1; return; } Console.WriteLine($"Will perform graceful shutdown when PID {Arguments.ShutdownWhenPidExits} exits."); MonitoredShutdownProcess.Exited += (s, a) => { Console.WriteLine($"PID {Arguments.ShutdownWhenPidExits} has exited, shutting down..."); Stop(); }; MonitoredShutdownProcess.EnableRaisingEvents = true; } OnStart(); if (Arguments.ServiceStartupMode == ServiceStartupMode.CommandLineInteractive) { Thread.Sleep(10); // Allow any startup log messages to flush to Console. Console.Title = ServiceName; if (Arguments.ConsoleOutputMode == ConsoleOutputMode.Color) { Console.ForegroundColor = ConsoleColor.Green; Console.Write("Service initialized in interactive mode (command line). Press "); Console.ForegroundColor = ConsoleColor.White; Console.BackgroundColor = ConsoleColor.DarkCyan; Console.Write("[Alt+S]"); Console.ForegroundColor = ConsoleColor.Green; Console.BackgroundColor = ConsoleColor.Black; Console.WriteLine(" to stop the service gracefully."); Console.ForegroundColor = ConsoleColor.Gray; } else { Console.WriteLine("Service initialized in interactive mode (command line). Press [Alt+S] to stop the service gracefully."); } Task.Factory.StartNew(() => { while (true) { var key = Console.ReadKey(true); if (key.Key == ConsoleKey.S && key.Modifiers == ConsoleModifiers.Alt) { Stop(); break; } } }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); } else { Console.WriteLine("Service initialized in non-interactive mode (command line). Waiting for stop request..."); } StopEvent.Reset(); ServiceStartedEvent.SetResult(null); StopEvent.WaitOne(); Console.WriteLine(" *** Shutting down... *** "); Task.Run(() => OnStop()).Wait(Arguments.OnStopWaitTime ?? TimeSpan.FromSeconds(10)); ServiceStartedEvent = new TaskCompletionSource <object>(); ServiceStoppedEvent.SetResult(null); MonitoredShutdownProcess?.Dispose(); if (Arguments.ServiceStartupMode == ServiceStartupMode.CommandLineInteractive) { if (Arguments.ConsoleOutputMode == ConsoleOutputMode.Color) { Console.BackgroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.Black; Console.WriteLine(" *** Shutdown complete. Press any key to exit. *** "); Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.Gray; } else { Console.WriteLine(" *** Shutdown complete. Press any key to exit. *** "); } Console.ReadKey(true); } } }
/// <summary> /// Start the service, auto detecting between Windows service and command line. Always blocks until service is stopped. /// </summary> public void Run(ServiceArguments argumentsOverride = null) { ServiceGracefullyStopped = new TaskCompletionSource <StopResult>(); try { Arguments = argumentsOverride ?? new ServiceArguments(System.Environment.GetCommandLineArgs().Skip(1).ToArray()); } catch (ArgumentException ex) { Console.WriteLine(ex.Message); Console.WriteLine(ServiceArguments.GetHelpDocumentation()); return; } if (argumentsOverride == null && ServiceArguments.IsHelpRequired(System.Environment.GetCommandLineArgs())) { Console.WriteLine(ServiceArguments.GetHelpDocumentation()); return; } if (Arguments.ServiceStartupMode == ServiceStartupMode.WindowsService) { Trace.WriteLine("Service starting as a Windows service..."); WindowsService = new DelegatingServiceBase(ServiceName, OnWindowsServiceStart, OnWindowsServiceStop); if (argumentsOverride == null) { Arguments = null; // Ensures OnWindowsServiceStart reloads parameters passed from Windows Service Manager. } ServiceBase.Run(WindowsService); // This calls OnWindowsServiceStart() on a different thread and blocks until the service stops. } else if (Arguments.ServiceStartupMode == ServiceStartupMode.VerifyConfigurations) { OnVerifyConfiguration(); } else { if (Arguments.ShutdownWhenPidExits != null) { try { MonitoredShutdownProcess = Process.GetProcessById(Arguments.ShutdownWhenPidExits.Value); } catch (ArgumentException e) { Console.WriteLine($"Service cannot start because monitored PID {Arguments.ShutdownWhenPidExits} is not running. Exception: {e}"); System.Environment.ExitCode = 1; ServiceGracefullyStopped.SetResult(StopResult.None); return; } Console.WriteLine($"Will perform graceful shutdown when PID {Arguments.ShutdownWhenPidExits} exits."); MonitoredShutdownProcess.Exited += (s, a) => { Console.WriteLine($"PID {Arguments.ShutdownWhenPidExits} has exited, shutting down..."); Stop(); }; MonitoredShutdownProcess.EnableRaisingEvents = true; } try { OnStart(); } catch (Exception e) { ServiceStartedEvent.TrySetException(e); throw; } if (Arguments.ServiceStartupMode == ServiceStartupMode.CommandLineInteractive) { Thread.Sleep(10); // Allow any startup log messages to flush to Console. Console.Title = ServiceName; if (Arguments.ConsoleOutputMode == ConsoleOutputMode.Color) { Console.ForegroundColor = ConsoleColor.Green; Console.Write("Service initialized in interactive mode (command line). Press "); Console.ForegroundColor = ConsoleColor.White; Console.BackgroundColor = ConsoleColor.DarkCyan; Console.Write("[Alt+S]"); Console.ForegroundColor = ConsoleColor.Green; Console.BackgroundColor = ConsoleColor.Black; Console.WriteLine(" to stop the service gracefully."); Console.ForegroundColor = ConsoleColor.Gray; } else { Console.WriteLine("Service initialized in interactive mode (command line). Press [Alt+S] to stop the service gracefully."); } Task.Factory.StartNew(() => { while (true) { var key = Console.ReadKey(true); if (key.Key == ConsoleKey.S && key.Modifiers == ConsoleModifiers.Alt) { Stop(); break; } } }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); } else { Console.WriteLine("Service initialized in non-interactive mode (command line). Waiting for stop request..."); } StopEvent.Reset(); ServiceStartedEvent.SetResult(null); StopEvent.WaitOne(); Console.WriteLine(" *** Shutting down... *** "); var maxShutdownTime = TimeSpan.FromSeconds((Arguments.OnStopWaitTimeSec ?? 0) + (Arguments.ServiceDrainTimeSec ?? 0)); bool isServiceGracefullyStopped = Task.Run(() => OnStop()).Wait(maxShutdownTime); if (isServiceGracefullyStopped == false) { Console.WriteLine($" *** Service failed to stop gracefully in the allotted time ({maxShutdownTime}), continuing with forced shutdown. *** "); } ServiceStartedEvent = new TaskCompletionSource <object>(); ServiceGracefullyStopped.SetResult(isServiceGracefullyStopped ? StopResult.Graceful : StopResult.Force); MonitoredShutdownProcess?.Dispose(); if (Arguments.ServiceStartupMode == ServiceStartupMode.CommandLineInteractive) { if (Arguments.ConsoleOutputMode == ConsoleOutputMode.Color) { Console.BackgroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.Black; Console.WriteLine(" *** Shutdown complete. Press any key to exit. *** "); Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.Gray; } else { Console.WriteLine(" *** Shutdown complete. Press any key to exit. *** "); } Console.ReadKey(true); } } }
/// <summary> /// Start the service, autodetecting between Windows service and command line. Always blocks until service is stopped. /// </summary> public void Run(ServiceArguments argumentsOverride = null) { ServiceGracefullyStopped = new TaskCompletionSource <StopResult>(); Arguments = argumentsOverride ?? new ServiceArguments(Environment.GetCommandLineArgs().Skip(1).ToArray()); CurrentApplicationInfo.Init(ServiceName, Arguments.InstanceName, InfraVersion); if (Arguments.ShutdownWhenPidExits != null) { try { MonitoredShutdownProcess = Process.GetProcessById(Arguments.ShutdownWhenPidExits.Value); } catch (ArgumentException e) { Console.WriteLine($"Service cannot start because monitored PID {Arguments.ShutdownWhenPidExits} is not running. Exception: {e}"); Environment.ExitCode = 1; ServiceGracefullyStopped.SetResult(StopResult.None); return; } Console.WriteLine($"Will perform graceful shutdown when PID {Arguments.ShutdownWhenPidExits} exits."); MonitoredShutdownProcess.Exited += (s, a) => { Console.WriteLine($"PID {Arguments.ShutdownWhenPidExits} has exited, shutting down..."); Stop(); }; MonitoredShutdownProcess.EnableRaisingEvents = true; } OnStart(); if (Arguments.ServiceStartupMode == ServiceStartupMode.CommandLineInteractive) { Thread.Sleep(10); // Allow any startup log messages to flush to Console. Console.Title = ServiceName; if (Arguments.ConsoleOutputMode == ConsoleOutputMode.Color) { Console.ForegroundColor = ConsoleColor.Green; Console.Write("Service initialized in interactive mode (command line). Press "); Console.ForegroundColor = ConsoleColor.White; Console.BackgroundColor = ConsoleColor.DarkCyan; Console.Write("[Alt+S]"); Console.ForegroundColor = ConsoleColor.Green; Console.BackgroundColor = ConsoleColor.Black; Console.WriteLine(" to stop the service gracefully."); Console.ForegroundColor = ConsoleColor.Gray; } else { Console.WriteLine("Service initialized in interactive mode (command line). Press [Alt+S] to stop the service gracefully."); } Task.Factory.StartNew(() => { while (true) { var key = Console.ReadKey(true); if (key.Key == ConsoleKey.S && key.Modifiers == ConsoleModifiers.Alt) { Stop(); break; } } }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); } else { Console.WriteLine("Service initialized in non-interactive mode (command line). Waiting for stop request..."); } StopEvent.Reset(); ServiceStartedEvent.SetResult(null); StopEvent.WaitOne(); Console.WriteLine(" *** Shutting down... *** "); var maxShutdownTime = TimeSpan.FromSeconds(Arguments.OnStopWaitTimeSec ?? 0); bool isServiceGracefullyStopped = Task.Run(() => OnStop()).Wait(maxShutdownTime); if (isServiceGracefullyStopped == false) { Console.WriteLine($" *** Service failed to stop gracefully in the allotted time ({maxShutdownTime}), continuing with forced shutdown. *** "); } ServiceStartedEvent = new TaskCompletionSource <object>(); ServiceGracefullyStopped.SetResult(isServiceGracefullyStopped ? StopResult.Graceful : StopResult.Force); MonitoredShutdownProcess?.Dispose(); if (Arguments.ServiceStartupMode == ServiceStartupMode.CommandLineInteractive) { if (Arguments.ConsoleOutputMode == ConsoleOutputMode.Color) { Console.BackgroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.Black; Console.WriteLine(" *** Shutdown complete. Press any key to exit. *** "); Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.Gray; } else { Console.WriteLine(" *** Shutdown complete. Press any key to exit. *** "); } Console.ReadKey(true); } }
protected override void Read() { using (var reader = new StreamReader(_fileName)) { // Similar to EventMessages.ReadOuterXml(), but send the messages to the handler as we // read them. var adaptor = new XmlReadAdaptor(new XmlTextReader(reader), Xml.Namespace); if (adaptor.IsReadingElement(Xml.EventMessagesElement)) { var messages = new EventMessages(); while (adaptor.ReadElement(Xml.EventMessageElement)) { // Check the reader wait handles - should we stop or pause? if (StopEvent.WaitOne(0, false)) { return; } if (PauseEvent.WaitOne(0, false)) { // Paused - wait for stop or continue. var pauseHandles = new[] { StopEvent, ContinueEvent }; switch (WaitHandle.WaitAny(pauseHandles)) { case 0: return; // Stop. case 1: break; // Continue. } } var message = new EventMessage(); message.ReadXml(adaptor.XmlReader); adaptor.ReadEndElement(); // Send to the message handler, if we have enough. messages.Add(message); if (messages.Count == Constants.MessageComponents.EventFile.MessageReaderBatchSize) { HandleEventMessages(messages); messages = new EventMessages(); } } // Send any remaining messages to the message handler. if (messages.Count > 0) { HandleEventMessages(messages); } } } OnExistingMessagesRead(System.EventArgs.Empty); }