Должен ли я использовать Timer, ThreadPool, AutoResetEvent или «объединить» с олицетворением? - PullRequest
2 голосов
/ 19 января 2011

После прочтения ТАК я понимаю, что Thread.Sleep это плохая идея .Вместо этого общий консенсус заключается в том, что задачи на стороне сервера должны использовать Timer, threadpool или, возможно, Join().

Одна статья упоминает о трудностях при утилизациитаймер.

В другой статье упоминается использование waitOne

Вопрос

Какой правильный подход использовать при запускедлительное задание, которое будет повторяться каждые 30 секунд, 1 минуту или 5 минут?Ограничение состоит в том, что ЕСЛИ предыдущий запуск этой задачи длиннее интервала (32 секунды или 7 минут), то я хочу, чтобы опция либо убивала этот предыдущий экземпляр, либо не выполняла новый экземпляр.

AВозможно, я намерен использовать олицетворение в этих потоках, используя WindowsImpersionationContext , P / Invoke LogonUserEX или DCOMShim при необходимости.

Я не уверен, какой подход и почему.

Возможный ответ 1

Этот пример выглядит простым, с минимальным беспорядком кода

    // initially set to a "non-signaled" state, ie will block
    // if inspected
   private readonly AutoResetEvent _isStopping = new AutoResetEvent(false);
    /// <summary>
    /// from...
    /// /1607526/system-timers-timer-threading-timer-protiv-potoka-s-whileloop-thread-sleep-dlya-periodicheskih-zadach#1607532
    /// </summary>
    public void SampleDelay1()
    {
        TimeSpan waitInterval = TimeSpan.FromMilliseconds(1000);

        // will block for 'waitInterval', unless another thread,
        // say a thread requesting termination, wakes you up. if
        // no one signals you, WaitOne returns false, otherwise
        // if someone signals WaitOne returns true
        for (; !_isStopping.WaitOne(waitInterval); )
        {
            // do your thang!
        }
    }

Возможный ответ 2

В этом примере представлены аналогичные функции, но используются анонимные типы, которые могут быть недопустимы в компаниях, которые не допускают этого в своем стандарте кодирования.

 /// <summary>
    /// Disposable Timer instance from 
    /// /325414/sravnite-ispolzuya-thread-sleep-i-timer-dlya-otlozhennogo-vypolneniya
    /// </summary>
    class TimerStackOverFlow
    {
   // Created by Roy Feintuch 2009
        // Basically we wrap a timer object in order to send itself as a context in order
        // to dispose it after the cb invocation finished. This solves the problem of timer 
        // being GCed because going out of context
        public static void DoOneTime(ThreadStart cb, TimeSpan dueTime)
        {
            var td = new TimerDisposer();
            // Is the next object System.Timers, or System.Threading
            var timer = new Timer(myTdToKill =>
            {
                try
                {
                    cb();
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("[DoOneTime] Error occured while invoking delegate. {0}", ex), "[OneTimer]");
                }
                finally
                {
                    ((TimerDisposer)myTdToKill).InternalTimer.Dispose();
                }
            },
                        td, dueTime, TimeSpan.FromMilliseconds(-1));

            td.InternalTimer = timer;
        }
    }

    class TimerDisposer
    {
        public Timer InternalTimer { get; set; }
    }

1 Ответ

0 голосов
/ 19 января 2011

Я использовал ваш первый подход много раз, и он хорошо работает.

Вторым решением является общая инкапсуляция основанного на времени триггера для одноразового события. Если вы смотрите на повторяющиеся события, то этот подход кажется мне излишне сложным без очевидной выгоды от дополнительной сложности.

...