문제

지정된 시간 동안 달리기를 지연시켜야하는 방법이 있습니다.

내가 사용해야할까요

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

또는

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

나는 몇 가지를 읽었습니다 조항 사용에 대해 Thread.Sleep 나쁜 디자인입니다. 그러나 나는 이유를 정말로 이해하지 못한다.

그러나 타이머를 사용하기 위해 타이머는 방법을 처리합니다. 실행이 지연되었으므로 타이머를 처리하는 방법을 모르겠습니다. 의견 있으십니까?

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

도움이 되었습니까?

해결책

한 가지 차이점은 그 것입니다 System.Threading.Timer 매번 새 스레드를 만들지 않고 스레드 풀 스레드에서 콜백을 발송합니다. 응용 프로그램의 수명 동안 두 번 이상 발생해야한다면, 이렇게하면 많은 스레드를 생성하고 파괴하는 오버 헤드 (기사에서 지적한 것처럼 매우 자원 집약적 인 프로세스)가 절약됩니다. 풀에서 나사산을 재사용하면 한 번에 하나 이상의 타이머가 있으면 한 번에 실행되는 스레드가 적을 수 있습니다 (상당한 자원을 저장 함).

다시 말해, Timer 훨씬 더 효율적일 것입니다. 그 이후로 더 정확할 수도 있습니다 Thread.Sleep 지정한 시간이 지정할 수있는 한 최소한 기다릴 수 있습니다 (OS는 훨씬 더 오래 잠을 잘 수 있습니다). 부여된, Timer 여전히 정확하지는 않지만 의도는 가능한 한 지정된 시간에 가까운 콜백을 발사하는 것이지만 반드시 의도는 아닙니다. Thread.Sleep.

파괴에 관해서 Timer, 콜백은 매개 변수를 수락 할 수 있으므로 Timer 콜백에서 매개 변수 및 호출 Dispose로 자체적으로 (이것을 시도하지는 않았지만 - 콜백 중에 타이머가 잠겨있을 수 있다고 생각합니다).

편집 : 아니요, 당신은 이것을 할 수 없다고 생각합니다. 콜백 매개 변수를 지정해야하기 때문입니다. 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로 무언가를 한 다음 a를 사용합니다 System.Windows.Forms.Timer UI 스레드에서 콜백을 실행하기 때문에 아마도 더 나은 내기 일 것입니다. 그러나 이것이 사실이 아니라면 Thread.Sleep vs. Threading.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);

특정 시간 동안 신청서를 일시 중지하고 싶다면 Thread.sleep가 괜찮다고 생각합니다. 사람들이 그것이 나쁜 디자인이라고 말하는 이유는 대부분의 상황에서 사람들이 실제로 응용 프로그램이 일시 중지되기를 원하지 않기 때문입니다.

예를 들어, 프로그래머가 소켓이 메일을 검색하는 동안 대기하기 위해 Thread.Sleep (1000)를 사용하는 POP3 클라이언트에서 작업하고있었습니다. 이러한 상황에서는 소켓이 완료된 후 이벤트 핸들러를 소켓에 연결하고 계속 프로그램 실행을하는 것이 더 낫습니다.

Eric의 솔루션과 유사한 솔루션을 구현 한 것을 기억합니다. 그러나 이것은 일하는 것입니다;)

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; }
    }

제가 시스템으로 가지고있는 유일한 쇠고기는 대부분의 시간이 투표 서비스에서 장기 지연 (시간, 분)에 사용 된 것을 보았고 개발자는 종종 이벤트를 시작하는 것을 잊어 버린다는 것입니다. 전에 그들은 타이머를 시작합니다. 즉, 앱이나 서비스를 시작하면 실제로 실행되기 전에 타이머가 경과 할 때까지 기다려야합니다.

물론, 이것은 타이머에 문제가되지 않지만, 오용하기가 너무 쉽기 때문에 종종 부적절하게 사용된다고 생각합니다.

@Miniscalope no no no no n't restle pool.registerwaitforsingleobject tiremer, system.threading.timer는 시간이 경과하고 대기 핸들이 필요하지 않을 때 스레드 풀 스레드에서 실행될 콜백을 대기열합니다. 단일 객체를 기다릴 때 대기합니다. 이벤트가 신호를 보내기를 기다리는 ThreadPool 스레드를 묶거나 스레드가 콜백을 호출하기 전에 만료 될 시간 초과가 만료됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top