code

지연된 실행을 위해 Thread.Sleep 및 Timer 사용 비교

codestyles 2021. 1. 8. 08:14
반응형

지연된 실행을 위해 Thread.Sleep 및 Timer 사용 비교


지정된 시간 동안 실행을 지연시켜야하는 방법이 있습니다.

내가 사용해야 할까

Thread thread = new Thread(() => {
    Thread.Sleep(millisecond);
    action();
});
thread.IsBackground = true;
thread.Start();

또는

Timer timer = new Timer(o => action(), null, millisecond, -1);

사용 관한 기사읽은 적이 Thread.Sleep있습니다. 그러나 나는 그 이유를 정말로 이해하지 못한다.

그러나 Timer를 사용하기 위해 Timer에는 dispose 방식이 있습니다. 실행이 지연 되었기 때문에 Timer의 폐기 방법을 모르겠습니다. 의견 있으십니까?

또는 지연된 실행에 대한 대체 코드가있는 경우에도 감사합니다.


한 가지 차이점은 System.Threading.Timer매번 새 스레드를 생성하는 대신 스레드 풀 스레드에서 콜백 디스패치한다는 것입니다. 응용 프로그램의 수명 동안이 작업이 두 번 이상 발생해야하는 경우 스레드 (참조 문서에서 지적한대로 매우 리소스 집약적 인 프로세스)를 만들고 파괴하는 오버 헤드를 줄일 수 있습니다. 풀에서 스레드를 재사용하기 만하면됩니다. 한 번에 둘 이상의 타이머가 실행되는 경우 한 번에 실행되는 스레드 수가 줄어 듭니다 (또한 상당한 리소스 절약).

즉, Timer훨씬 더 효율적일 것입니다. 또한 Thread.Sleep지정한 시간만큼만 대기하도록 보장 되기 때문에 더 정확할 수 있습니다 (OS가 훨씬 더 오랫동안 절전 모드로 전환 할 수 있음). 확실히 Timer정확하지는 않지만 가능한 한 지정된 시간에 가깝게 콜백을 실행하는 것이지만, 반드시 Thread.Sleep.

를 파괴하는 것과 관련 Timer하여 콜백은 매개 변수를 받아 들일 수 있으므로 Timer자체를 매개 변수로 전달 하고 콜백에서 Dispose를 호출 할 수 있습니다 (내가 시도한 적은 없지만 Timer가 콜백 중에 잠김).

편집 : 아니요, Timer생성자 자체 에서 콜백 매개 변수를 지정해야하므로이 작업을 수행 할 수 없습니다 .

아마 이런 건가요? (다시, 실제로 시도하지 않았습니다)

class TimerState
{
    public Timer Timer;
}

... 타이머를 시작하려면 :

TimerState state = new TimerState();

lock (state)
{
    state.Timer = new Timer((callbackState) => {
        action();
        lock (callbackState) { callbackState.Timer.Dispose(); }
        }, state, millisecond, -1);
}

잠금은 타이머 콜백이 Timer필드가 설정 되기 전에 타이머를 해제하지 못하도록해야합니다 .


부록 : 댓글 작성자가 지적했듯이 action()UI로 무언가를 System.Windows.Forms.Timer수행하면 UI 스레드에서 콜백을 실행하므로 a 를 사용하는 것이 더 나은 방법 일 것입니다. 이 경우가 아니라, 그것은 아래의 경우, Thread.SleepThreading.Timer, Threading.Timer길을 가야하는 것입니다.


ThreadPool.RegisterWaitForSingleObject타이머 대신 사용 :

//Wait 5 seconds then print out to console. 
//You can replace AutoResetEvent with a Semaphore or EventWaitHandle if you want to execute the command on those events and/or the timeout
System.Threading.ThreadPool.RegisterWaitForSingleObject(new AutoResetEvent(false), (state, bTimeout) => Console.WriteLine(state), "This is my state variable", TimeSpan.FromSeconds(5), true);

I think Thread.Sleep is fine if you really want to pause the application for a specified amount of time. I think the reason people say it is a bad design is because in most situations people don't actually want the application to pause.

For example, I was working on a pop3 client where the programmer was using Thread.Sleep(1000) to wait while the socket retrieved mail. In that situation it was better to hook up an event handler to the socket and continuing program execution after the socket had completed.


I remember implementing a solution similar to Eric's one. This is however a working one ;)

class OneTimer
    {
        // 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();
            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; }
    }

The only beef that I have with the System.Timer is that most of the time I have seen it used for long delays (hours, minutes) in polling services and developers often forget to launch the event Before they start the timer. This means that if I start the app or service, I have to wait until the timer elapses (hours, minutes) before it actually executes.

Sure, this is not a problem with the timer, but I think that its often used improperly by because its just too easy to misuse.


@miniscalope No don't use ThreadPool.RegisterWaitForSingleObject instead of timer, System.Threading.Timer will queue a callback to be executed on a thread pool thread when the time has elapsed and doesn't require a wait handle, wait for single object will tie up a threadpool thread waiting for the event to be signalled or the timeout to expire before the thread calls the callback.

ReferenceURL : https://stackoverflow.com/questions/391621/compare-using-thread-sleep-and-timer-for-delayed-execution

반응형