C #의 System.Threading.Timer가 작동하지 않는 것 같습니다. 3 초마다 매우 빠르게 실행됩니다
타이머 객체가 있습니다. 매분마다 실행되기를 원합니다. 특히, OnCallBack메소드를 실행해야 하며 OnCallBack메소드가 실행되는 동안 비활성화됩니다 . OnCallBack메소드가 완료 되면 (a OnCallBack) 타이머를 다시 시작합니다.
여기 내가 지금 가지고있는 것입니다 :
private static Timer timer;
private static void Main()
{
timer = new Timer(_ => OnCallBack(), null, 0, 1000 * 10); //every 10 seconds
Console.ReadLine();
}
private static void OnCallBack()
{
timer.Change(Timeout.Infinite, Timeout.Infinite); //stops the timer
Thread.Sleep(3000); //doing some long operation
timer.Change(0, 1000 * 10); //restarts the timer
}
그러나 작동하지 않는 것 같습니다. 3 초마다 매우 빠르게 실행됩니다. 마침표를 올리더라도 (1000 * 10). 눈을 멀게하는 것 같습니다1000 * 10
내가 뭘 잘못 했어?
이것은 System.Threading.Timer의 올바른 사용법이 아닙니다. 타이머를 인스턴스화 할 때는 거의 항상 다음을 수행해야합니다.
_timer = new Timer( Callback, null, TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite );
간격이 경과하면 타이머가 한 번만 틱하도록 지시합니다. 그런 다음 콜백 기능에서 작업이 완료된 후 이전이 아닌 타이머를 변경합니다. 예:
private void Callback( Object state )
{
// Long running operation
_timer.Change( TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite );
}
따라서 동시성이 없기 때문에 잠금 메커니즘이 필요하지 않습니다. 타이머는 다음 간격이 경과 한 후 다음 콜백 + 장기 실행 시간을 발생시킵니다.
정확히 N 밀리 초로 타이머를 실행해야하는 경우 Stopwatch를 사용하여 장기 실행 시간을 측정 한 다음 Change 메서드를 적절하게 호출하는 것이 좋습니다.
private void Callback( Object state )
{
Stopwatch watch = new Stopwatch();
watch.Start();
// Long running operation
_timer.Change( Math.Max( 0, TIME_INTERVAL_IN_MILLISECONDS - watch.ElapsedMilliseconds ), Timeout.Infinite );
}
나는 강력하게 - 사람이 .NET을 수행하고, 제프리 리히터의 책을 읽을 수있다 CLR 사용하고 격려 C #을 통해 CLR을 가능한 한 빨리를 읽기. 타이머와 스레드 풀에 대한 자세한 설명이 있습니다.
타이머를 중지 할 필요는 없습니다 . 이 게시물의 멋진 솔루션을 참조하십시오 .
"타이머가 콜백 메소드를 계속 실행하도록 할 수 있지만 재진입 할 수없는 코드를 Monitor.TryEnter / Exit에 래핑 할 수 있습니다.이 경우 타이머를 중지 / 다시 시작할 필요가 없습니다. 중복 된 호출은 잠금을 획득하지 않고 즉시 돌아 오지 않습니다."
private void CreatorLoop(object state)
{
if (Monitor.TryEnter(lockObject))
{
try
{
// Work here
}
finally
{
Monitor.Exit(lockObject);
}
}
}
System.Threading.Timer를 사용하고 있습니까?
그렇지 않은 경우 System.Timers.Timer에는 편리한 Start () 및 Stop () 메서드가 있으며 AutoReset 속성은 false로 설정할 수 있으므로 Stop ()이 필요하지 않고 실행 후 Start ()를 호출하기 만하면됩니다.
나는 단지 할 것이다 :
private static Timer timer;
private static void Main()
{
timer = new Timer(_ => OnCallBack(), null, 1000 * 10,Timeout.Infinite); //in 10 seconds
Console.ReadLine();
}
private static void OnCallBack()
{
timer.Dispose();
Thread.Sleep(3000); //doing some long operation
timer = new Timer(_ => OnCallBack(), null, 1000 * 10,Timeout.Infinite); //in 10 seconds
}
periodicy를 직접 제어하려고하므로 period 매개 변수를 무시하십시오.
당신이 지정 유지하기 때문에 원래 코드는 가능한 한 빨리 실행 0에 대한 dueTime매개 변수입니다. 보낸 사람 Timer.Change:
dueTime이 0이면 콜백 메소드가 즉시 호출됩니다.
var span = TimeSpan.FromMinutes(2);
var t = Task.Factory.StartNew(async delegate / () =>
{
this.SomeAsync();
await Task.Delay(span, source.Token);
}, source.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
source.Cancel(true/or not);
// or use ThreadPool(whit defaul options thread) like this
Task.Start(()=>{...}), source.Token)
내부에 루프 스레드를 사용하고 싶다면 ...
public async void RunForestRun(CancellationToken token)
{
var t = await Task.Factory.StartNew(async delegate
{
while (true)
{
await Task.Delay(TimeSpan.FromSeconds(1), token)
.ContinueWith(task => { Console.WriteLine("End delay"); });
this.PrintConsole(1);
}
}, token) // drop thread options to default values;
}
// And somewhere there
source.Cancel();
//or
token.ThrowIfCancellationRequested(); // try/ catch block requred.
'Programing' 카테고리의 다른 글
| Spark DataFrame에 새 열을 어떻게 추가합니까 (PySpark 사용)? (0) | 2020.08.05 |
|---|---|
| Java에서 동일한 catch 블록에서 두 가지 예외를 잡을 수 있습니까? (0) | 2020.08.05 |
| Android 디자인 라이브러리-부동 작업 버튼 패딩 / 여백 문제 (0) | 2020.08.05 |
| 리눅스 쉘 스크립트에서 메일 보내기 (0) | 2020.08.05 |
| sklearn에서 가져 오기에서 ImportError : 이름 check_build를 가져올 수 없습니다 (0) | 2020.08.05 |