public void Stop()
        {
            if (_thread == null)
            {
                throw new Exception(string.Format("Can't stop thread '{0}': it isn't created", Name));
            }

            if ((_thread.ThreadState & ThreadState.Unstarted) != 0)
            {
                throw new Exception(string.Format("Can't stop thread '{0}': it is in inpropriate state '{1}", Name, _thread.ThreadState));
            }

            _evStop.Set();
            if (!_thread.Join(StopTimeoutMS))
            {
                _logger.Warn("Thread '{0}' was timeot at stopping: aborting", Name);
                _thread.Interrupt();
                _thread.Abort();
            }

            _thread = null;
            _evStop.Dispose();
            _evStop = null;
            _evHasData.Dispose();
            _evHasData = null;
        }
        void processMail(CancellationToken token)
        {
            if (_mailsActiveCount > _maxParallelMessages)
            {
                return;
            }

            Interlocked.Increment(ref _mailsActiveCount);
            QueuedMail msg = null;

            try {
                if (!token.IsCancellationRequested && _mainQueue.TryDequeue(out msg))
                {
                    DateTime dt = DateTime.UtcNow;
                    using (ISmpClient cli = _clifac.Create())
                    {
                        cli.Send(msg.Msg);
                    }

                    if ((DateTime.UtcNow - dt).TotalSeconds > WarnTimeInSec)
                    {
                        _logger.Warn("Sending mail '{0}', to {1} took extratime: {2}s", msg.Msg.Subject, msg.Msg.Recipients, (DateTime.UtcNow - dt).TotalSeconds);
                    }

                    msg.Msg.Dispose();
                }
            }
            catch (Exception ex)
            {
                _logger.Exception(string.Format("On sending news, queue size = {0}", _mainQueue.Count), ex);
                if (!token.IsCancellationRequested)
                {
                    msg.LastError = ex;
                    _retryQueue.Enqueue(msg);
                    startRetrying();
                }
            }
            finally {
                Interlocked.Decrement(ref _mailsActiveCount);
            }

            if (_mainQueue.Count > 0 && !token.IsCancellationRequested)
            {
                startSending();
            }
        }
        protected virtual void Dispose(bool disposing)
        {
            Thread.VolatileWrite(ref _disposed, 1);

            if (disposing)
            {
                SafeReleasers.ReleaseTimer(ref _tmPostoned, null, true);

                if (!_queueFinished.Wait(WaitOnDisposeMs))
                {
                    _logger.Warn("Timeout '{0}' ms was reached at disposing '{1}', queued tasks {2}", WaitOnDisposeMs, Name, _requestsCount);
                    dumpCurrentRequests();
                }
                try { _queueFinished.Dispose(); } catch {}
                Interlocked.Exchange(ref _queueFinished, null);
            }
        }
示例#4
0
        protected override void OnContinue()
        {
            base.OnContinue();

            base.OnPause();

            CancellationTokenSource src = new CancellationTokenSource();

            _logger.Info("Service '{0}' recieved OnContinue command", WinServiceName);
            Task <RuntimeServiceState> tsk = _stateMachine.Transit(RuntimeServiceState.Started, src.Token);

            tsk.ContinueWith((t) => src.Dispose());

            bool res = false;

            System.Diagnostics.Stopwatch w = System.Diagnostics.Stopwatch.StartNew();

            bool hasError = false;

            try {
                res = tsk.Wait(pauseResumeTimeoutMS);
            }
            catch (AggregateException ex)
            {
                hasError = true;
                _logger.Error("Service '{0}' failed to process OnContinue command", WinServiceName);
                ex.Handle((err) => {
                    if (err is OperationCanceledException)
                    {
                        _logger.Warn("Service '{0}' OnContinue was cancelled", WinServiceName);
                        if (_testMode)
                        {
                            Console.WriteLine(string.Format("Service '{0}' OnContinue was cancelled", WinServiceName));
                        }
                        return(true);
                    }
                    else
                    {
                        _logger.Exception(string.Format("Service '{0}' failed to process OnContinue command", WinServiceName), err);
                        if (_testMode)
                        {
                            Console.WriteLine(err.ToString());
                        }
                    }
                    return(true);
                });
            }
            catch (OperationCanceledException)
            {
                hasError = true;
                _logger.Warn("Service '{0}' OnContinue was cancelled", WinServiceName);
                if (_testMode)
                {
                    Console.WriteLine("Resuming has been cancelled");
                }
            }
            catch (Exception ex)
            {
                hasError = true;
                _logger.Exception(string.Format("Service '{0}' failed to process OnContinue command", WinServiceName), ex);
                if (_testMode)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
            finally {
                w.Stop();
            }

            if (!res)
            {
                try { src.Cancel(); } catch {}
                if (!hasError)
                {
                    string msg = string.Format("Timeout of resuming service '{0}', elapsed: {1:hh\\:mm\\:ss\\.ff}", WinServiceName, w.Elapsed);
                    _logger.Error(msg);
                    if (_testMode)
                    {
                        Console.WriteLine(msg);
                    }
                }


#pragma warning disable 4014
                _logger.Info("Requesting additional time and stop...");
                requestPauseResumeTime();
                //try {_stateMachine.Transit(RuntimeServiceState.Stopped, CancellationToken.None).Wait(startStopTimeoutMS);} catch {}
                //часть сервисов могла запуститься, поэтому состояние хоста не целостное (сервисы в разных состояниях), и мы всё останавливаем
                try { stop(_stateMachine.State, RuntimeServiceState.Stopped, CancellationToken.None); } catch {}
#pragma warning restore 4014

                throw new Exception(hasError ? "OnContinue rolled back by error":"OnContinue rolled back by timeout");
            }

            _logger.Info("Service '{0}' successfully processed OnContinue command, elapsed: {1:hh\\:mm\\:ss\\.ff}", WinServiceName, w.Elapsed);
        }
示例#5
0
        public async Task <TState> Transit(TState newState, CancellationToken cts, object args = null)
        {
            if (_logTransitions)
            {
                _logger.Info("Machine '{0}' is about to transit {1} --> {2}", Name, State, newState);
            }

            if (!StateDef <TState> .IsValid(newState))
            {
                return(await compliteWithError(new Exception(string.Format("State '{0}' is invalid for machine '{1}'", newState, Name))));
            }

            if (IsInFinalState)
            {
                return(await compliteWithError(new Exception(string.Format("Machine '{0}' can't transit to state '{1}' because it is in final state '{2}'", Name, newState, _state.Final))));
            }

            int res = Interlocked.Exchange(ref _isInTransition, 1);             //блокировка транзишенов до тех пор, пока не заевршится текущий транзишен

            if (res != 0)
            {
                if (EqualityComparer <TState> .Default.Equals(newState, FinalState))               //разрешаем только рекурсивный Close
                {
                    _logger.Warn("Machine '{0}' started reqursive transition {1} --> {2}", Name, State, newState);
                }
                else
                {
                    return(await compliteWithError(new Exception(string.Format("In machine '{0}' reqursive transition {1} --> {2} has been detected", Name, State, newState))));
                }
            }

            TState transitionResult           = State;
            CancellationTokenRegistration reg = default(CancellationTokenRegistration);
            bool lockCleared = false;

            try {
                TState stateFrom = State;
                TransitionDef <TState> transition = getTransition(stateFrom, newState);
                if (transition == TransitionDef <TState> .Empty)
                {
                    throw new Exception(string.Format("Machine '{0}' didn't find transition {1} --> {2}", Name, stateFrom, newState));
                }

                if (_logTransitions)
                {
                    _logger.Info("Machine '{0}' is transiting {1} --> {2}", Name, stateFrom, newState);
                }

                if (transition.StateActivityAsync != null)
                {
                    try {
                        TransitionState = _state.GetTransitionalState(State, newState);
                        if (TransitionState != null)
                        {
                            onStateChanging(TransitionState.Value);
                        }

                        reg = cts.Register(() => { lockCleared = true; Interlocked.Exchange(ref _isInTransition, 0); });
                        transitionResult = await transition.StateActivityAsync(stateFrom, newState, cts, args).WithAllExceptions().ConfigureAwait(false);

                        cts.ThrowIfCancellationRequested();
                        State = transitionResult;
                        if (_logTransitions)
                        {
                            _logger.Info("Machine '{0}' transited {1} --> {2}", Name, stateFrom, newState);
                        }
                        onStateChanged(stateFrom, transitionResult);
                    }
                    catch (AggregateException ex)
                    {
                        _logger.Error("Machine '{0}' failed to transit {1} --> {2}", Name, stateFrom, newState);
                        onStateChanged(stateFrom, transitionResult, ex);
                        ex.Handle((err) => {
                            if (err is OperationCanceledException)
                            {
                                _logger.Warn("Machine '{0}' transition {1} --> {2} was cancelled", Name, stateFrom, newState);
                                return(true);
                            }
                            return(false);
                        });
                    }
                    catch (OperationCanceledException ce)
                    {
                        _logger.Warn("Machine '{0}' transition {1} --> {2} was cancelled", Name, stateFrom, newState);
                        onStateChanged(stateFrom, transitionResult, ce);
                    }
                    catch (Exception ex)
                    {
                        _logger.Exception(string.Format("Machine '{0}' failed to transit {1} --> {2}", Name, stateFrom, newState), ex);
                        onStateChanged(stateFrom, transitionResult, ex);
                        throw;
                    }
                }
                else
                {
                    State            = newState;
                    transitionResult = newState;
                    if (_logTransitions)
                    {
                        _logger.Info("Machine '{0}' transited {1} --> {2} with no action", Name, stateFrom, newState);
                    }
                    onStateChanged(stateFrom, newState);
                }
            }
            finally {
                if (!lockCleared)
                {
                    Interlocked.Exchange(ref _isInTransition, 0);
                    TransitionState = null;
                }
            }

            return(transitionResult);
        }