Beispiel #1
0
        /// <summary>
        /// <see cref="ServiceBase.OnStop"/> override.
        /// Cancels the internal <see cref="CancellationTokenSource"/> to signal stopping of the service if the service has not already been stopped.
        /// </summary>
        protected override void OnStop()
        {
            try
            {
                this.Status = AsyncServiceStatus.StopPending;

                // we only need to cancel the task if it hasn't already been cancelled
                if (!_runTask.IsCompleted)
                {
                    Debug.WriteLine("Cancelling RunTask...");
                    _cts.Cancel();
                }

                // await the end of all asynchronous tasks
                Debug.WriteLine("Thread.JoinAsync()");
                _contextThread.JoinAsync().GetAwaiter().GetResult();
            }

            catch (Exception e)
            {
                EventLog.WriteEntry(e.Message, EventLogEntryType.Error);
            }
            finally
            {
                this.Status = AsyncServiceStatus.Stopped;
            }
        }
Beispiel #2
0
        /// <summary>
        /// <see cref="ServiceBase.OnStart"/> override.
        /// Creates an internal <see cref="Task"/> which is run on the <see cref="AsyncContextThread"/> and awaits its completion without blocking.
        /// Appropriately sets ServiceBase.ExitCode depending on Task completion state and logs exceptions to Windows Application Eventlog.
        /// </summary>
        /// <param name="args">The commandline arguments passed to the service.</param>
        protected override void OnStart(string[] args)
        {
            _cts           = new CancellationTokenSource();
            _pts           = new PauseTokenSource();
            _contextThread = new AsyncContextThread();

            try
            {
                this.ExitCode = 0;
                this.Status   = AsyncServiceStatus.StartPending;

                // create a new long running task
                _runTask = _contextThread.Factory.Run(() => RunServiceAsync(args, _cts.Token, _pts.Token));

                // if the task completed normally, just stop the service and exit
                _runTask.ContinueWith(t => Stop(), CancellationToken.None,
                                      TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);

                // if the task was canceled in OnStop() just write a debug message
                _runTask.ContinueWith(t => Debug.WriteLine("ReceiveTask canceled"), CancellationToken.None,
                                      TaskContinuationOptions.OnlyOnCanceled, TaskScheduler.Default);

                // if the task faulted, handle the exception
                _runTask.ContinueWith(t => HandleException(t.Exception), CancellationToken.None,
                                      TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);

                // await the completion of the task without blocking the OnStart() call from SCM
                _runTask.WaitAsync(_cts.Token).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                EventLog.WriteEntry(e.Message, EventLogEntryType.Error);
            }
            finally
            {
                this.Status = AsyncServiceStatus.Running;
            }
        }
Beispiel #3
0
        /// <summary>
        /// <see cref="ServiceBase.OnContinue"/> override.
        /// Sets the internal <see cref="PauseTokenSource"/> to false to signal continuation of the service.
        /// </summary>
        /// <exception cref="NotSupportedException"></exception>
        protected override void OnContinue()
        {
#if (DEBUG)
            // only valid during DEBUG as SCM will not call OnContinue if PauseAndContinue is not set.
            if (!this.CanPauseAndContinue)
            {
                throw new NotSupportedException("Service is not configured to support PauseAndContinue.");
            }
#endif
            try
            {
                this.Status   = AsyncServiceStatus.ContinuePending;
                _pts.IsPaused = false;
            }
            catch (Exception e)
            {
                EventLog.WriteEntry(e.Message, EventLogEntryType.Error);
            }
            finally
            {
                this.Status = AsyncServiceStatus.Running;
            }
        }
 /// <summary>
 /// Initializes a new <see cref="AsyncServiceStatusChangedEventArgs"/> instance.
 /// </summary>
 /// <param name="from">The previous <see cref="AsyncServiceStatus"/> state of the service</param>
 /// <param name="to">The new <see cref="AsyncServiceStatus"/> state of the service</param>
 public AsyncServiceStatusChangedEventArgs(AsyncServiceStatus from, AsyncServiceStatus to)
 {
     this.FromStatus = from;
     this.ToStatus   = to;
 }