Microsoft MVP성태의 닷넷 이야기
WaitHandle.WaitOne 과 Stopwatch에 관한 질문 [링크 복사], [링크+제목 복사]
조회: 17023
글쓴 사람
윤용한 (yonghany at gmail.com)
홈페이지
첨부 파일
 
(연관된 글이 2개 있습니다.)

안녕하세요.
Stopwatch와 WaitOne에 대해 질문드립니다.
개발환경은 .NET 4.0이고 TPL을 사용 중입니다.
문제는 다음과 같습니다.
task가 매 1분마다 한번씩 서버에 데이터를 보내는데
이게 정확히 1분마다 수행되는게 아니고 시간이 점점 짧아집니다.
System.Thread.Timer를 이용해도 마찬가지로 약간의 밀리세컨드 오차가 발생하여 정확히 1분만다 수행이 안됩니다. 실행시간이 짧으면 괞찮겠지만 최소 16시간에서 36시간 동안 진행되는 작업이라, 시간이 흐를수록 오차가 점점 커져가서 16시간 정도 되면 거의 1시간 가량이 단축되어 버립니다..--;

오차를 줄이기 위해 매분마다 하는 작업시간도 계산해서 frequency에서 뺀 시간만큼 wait를 해도 오차가 줄어들긴하지만 없어지지는 않네요.

제 생각에는 Stopwatch는 HighResolution으로 계산이 되지만 WaitOne
에서 부동소수점이 절삭되어서 계속해서 오차가 생기는 거 같은데 (맞나요?)...

이러한 오차없이 정확한 시간에 수행되도록 하는 방법이 있나요?


TimeSpan frequency = new TimeSpan(0,1,0);
for (int step=1; step<960; step++)
{
  Stopwatch stopwatch = Stopwatch.StartNew();

  Log.InfoFormat("STEP, {0}, {1:00}:{2:00}", step, (int)(CurrentStep / 60.0), CurrentStep % 60.0);

  //
  // 작업수행 (여기서 걸리는 시간은 길어야 00:00:00.0120852 입니다)
  //
  stopwatch.Stop();

  // 여기서 wait하는 시간은 큰 차이가 없습니다.
  // 대략 00:00:59.9901087 정도
  // 하지만 WaitOne이 좀도 빨리 깨어나는 거 같습니다.
  Log.DebugFormat("MEASURE, {0}, WAIT={1}", stopwatch.Elapsed, (Frequency - stopwatch.Elapsed));
  token.WaitHandle.WaitOne(frequency - stopwatch.Elapased);
}

수행결과 : millisecond가 약간씩 틀려짐

2011-02-18 11:05:11,602 [10] INFO STEP, 1, 00:01
2011-02-18 11:06:11,603 [10] INFO STEP, 2, 00:02
2011-02-18 11:07:11,602 [10] INFO STEP, 3, 00:03
2011-02-18 11:08:11,602 [10] INFO STEP, 4, 00:04
2011-02-18 11:09:11,601 [10] INFO STEP, 5, 00:05
2011-02-18 11:10:11,600 [10] INFO STEP, 6, 00:06
2011-02-18 11:11:11,600 [10] INFO STEP, 7, 00:07
2011-02-18 11:12:11,599 [10] INFO STEP, 8, 00:08
2011-02-18 11:13:11,599 [10] INFO STEP, 9, 00:09
2011-02-18 11:14:11,599 [10] INFO STEP, 10, 00:10
2011-02-18 11:15:11,599 [10] INFO STEP, 11, 00:11
2011-02-18 11:16:11,598 [10] INFO STEP, 12, 00:12
2011-02-18 11:17:11,597 [10] INFO STEP, 13, 00:13
2011-02-18 11:18:11,597 [10] INFO STEP, 14, 00:14
2011-02-18 11:19:11,596 [10] INFO STEP, 15, 00:15
2011-02-18 11:20:11,596 [10] INFO STEP, 16, 00:16
2011-02-18 11:21:11,595 [10] INFO STEP, 17, 00:17
2011-02-18 11:22:11,595 [10] INFO STEP, 18, 00:18
2011-02-18 11:23:11,594 [10] INFO STEP, 19, 00:19
2011-02-18 11:24:11,593 [10] INFO STEP, 20, 00:20
2011-02-18 11:25:11,593 [10] INFO STEP, 21, 00:21
2011-02-18 11:26:11,592 [10] INFO STEP, 22, 00:22
2011-02-18 11:27:11,592 [10] INFO STEP, 23, 00:23
2011-02-18 11:28:11,591 [10] INFO STEP, 24, 00:24
2011-02-18 11:29:11,591 [10] INFO STEP, 25, 00:25
2011-02-18 11:30:11,590 [10] INFO STEP, 26, 00:26
2011-02-18 11:31:11,590 [10] INFO STEP, 27, 00:27
2011-02-18 11:32:11,589 [10] INFO STEP, 28, 00:28
2011-02-18 11:33:11,588 [10] INFO STEP, 29, 00:29
2011-02-18 11:34:11,588 [10] INFO STEP, 30, 00:30
2011-02-18 11:35:11,587 [10] INFO STEP, 31, 00:31
2011-02-18 11:36:11,587 [10] INFO STEP, 32, 00:32
2011-02-18 11:37:11,586 [10] INFO STEP, 33, 00:33
2011-02-18 11:38:11,586 [10] INFO STEP, 34, 00:34
2011-02-18 11:39:11,585 [10] INFO STEP, 35, 00:35

시간측정값
2011-02-18 11:05:11,613 [10] DEBUG MEASURE, 00:00:00.0111593, WAIT=00:00:59.9888403
2011-02-18 11:06:11,615 [10] DEBUG MEASURE, 00:00:00.0129216, WAIT=00:00:59.9870780
2011-02-18 11:07:11,613 [10] DEBUG MEASURE, 00:00:00.0111803, WAIT=00:00:59.9888193
2011-02-18 11:08:11,614 [10] DEBUG MEASURE, 00:00:00.0120852, WAIT=00:00:59.9879144
2011-02-18 11:09:11,614 [10] DEBUG MEASURE, 00:00:00.0131108, WAIT=00:00:59.9868892
2011-02-18 11:10:11,608 [10] DEBUG MEASURE, 00:00:00.0079609, WAIT=00:00:59.9920387
2011-02-18 11:11:11,609 [10] DEBUG MEASURE, 00:00:00.0089334, WAIT=00:00:59.9910662
2011-02-18 11:12:11,608 [10] DEBUG MEASURE, 00:00:00.0089188, WAIT=00:00:59.9910804
2011-02-18 11:13:11,610 [10] DEBUG MEASURE, 00:00:00.0114450, WAIT=00:00:59.9885546
2011-02-18 11:14:11,608 [10] DEBUG MEASURE, 00:00:00.0090173, WAIT=00:00:59.9909823
2011-02-18 11:15:11,609 [10] DEBUG MEASURE, 00:00:00.0102548, WAIT=00:00:59.9897448
2011-02-18 11:16:11,609 [10] DEBUG MEASURE, 00:00:00.0111414, WAIT=00:00:59.9888582
2011-02-18 11:17:11,608 [10] DEBUG MEASURE, 00:00:00.0110511, WAIT=00:00:59.9889485
2011-02-18 11:18:11,609 [10] DEBUG MEASURE, 00:00:00.0120560, WAIT=00:00:59.9879436
2011-02-18 11:19:11,608 [10] DEBUG MEASURE, 00:00:00.0120682, WAIT=00:00:59.9879314
2011-02-18 11:20:11,604 [10] DEBUG MEASURE, 00:00:00.0086704, WAIT=00:00:59.9913292
2011-02-18 11:21:11,603 [10] DEBUG MEASURE, 00:00:00.0081886, WAIT=00:00:59.9918110
2011-02-18 11:22:11,604 [10] DEBUG MEASURE, 00:00:00.0089399, WAIT=00:00:59.9910593
2011-02-18 11:23:11,604 [10] DEBUG MEASURE, 00:00:00.0099999, WAIT=00:00:59.9899997
2011-02-18 11:24:11,603 [10] DEBUG MEASURE, 00:00:00.0100089, WAIT=00:00:59.9899907
2011-02-18 11:25:11,604 [10] DEBUG MEASURE, 00:00:00.0110559, WAIT=00:00:59.9889437
2011-02-18 11:26:11,603 [10] DEBUG MEASURE, 00:00:00.0110989, WAIT=00:00:59.9889007
2011-02-18 11:27:11,599 [10] DEBUG MEASURE, 00:00:00.0071067, WAIT=00:00:59.9928929
2011-02-18 11:28:11,603 [10] DEBUG MEASURE, 00:00:00.0121991, WAIT=00:00:59.9878001
2011-02-18 11:29:11,604 [10] DEBUG MEASURE, 00:00:00.0130569, WAIT=00:00:59.9869427
2011-02-18 11:30:11,599 [10] DEBUG MEASURE, 00:00:00.0090432, WAIT=00:00:59.9909564
2011-02-18 11:31:11,599 [10] DEBUG MEASURE, 00:00:00.0090979, WAIT=00:00:59.9909017
2011-02-18 11:32:11,599 [10] DEBUG MEASURE, 00:00:00.0100611, WAIT=00:00:59.9899385
2011-02-18 11:33:11,598 [10] DEBUG MEASURE, 00:00:00.0100315, WAIT=00:00:59.9899680
2011-02-18 11:34:11,599 [10] DEBUG MEASURE, 00:00:00.0111119, WAIT=00:00:59.9888877
2011-02-18 11:35:11,598 [10] DEBUG MEASURE, 00:00:00.0118449, WAIT=00:00:59.9881547
2011-02-18 11:36:11,599 [10] DEBUG MEASURE, 00:00:00.0121087, WAIT=00:00:59.9878909
2011-02-18 11:37:11,593 [10] DEBUG MEASURE, 00:00:00.0072878, WAIT=00:00:59.9927114
2011-02-18 11:38:11,594 [10] DEBUG MEASURE, 00:00:00.0079937, WAIT=00:00:59.9920059
2011-02-18 11:39:11,594 [10] DEBUG MEASURE, 00:00:00.0092098, WAIT=00:00:59.9907898
2011-02-18 11:40:11,593 [10] DEBUG MEASURE, 00:00:00.0091826, WAIT=00:00:59.9908170
2011-02-18 11:41:11,594 [10] DEBUG MEASURE, 00:00:00.0100944, WAIT=00:00:59.9899052
2011-02-18 11:42:11,593 [10] DEBUG MEASURE, 00:00:00.0099744, WAIT=00:00:59.9900252
2011-02-18 11:43:11,599 [10] DEBUG MEASURE, 00:00:00.0162488, WAIT=00:00:59.9837508
2011-02-18 11:44:11,593 [10] DEBUG MEASURE, 00:00:00.0110981, WAIT=00:00:59.9889015
2011-02-18 11:45:11,594 [10] DEBUG MEASURE, 00:00:00.0120811, WAIT=00:00:59.9879184
2011-02-18 11:46:11,594 [10] DEBUG MEASURE, 00:00:00.0130508, WAIT=00:00:59.9869488
2011-02-18 11:47:11,593 [10] DEBUG MEASURE, 00:00:00.0130893, WAIT=00:00:59.9869103
2011-02-18 11:48:11,589 [10] DEBUG MEASURE, 00:00:00.0090250, WAIT=00:00:59.9909750
2011-02-18 11:49:11,588 [10] DEBUG MEASURE, 00:00:00.0091449, WAIT=00:00:59.9908547
2011-02-18 11:50:11,589 [10] DEBUG MEASURE, 00:00:00.0101693, WAIT=00:00:59.9898307
2011-02-18 11:51:11,588 [10] DEBUG MEASURE, 00:00:00.0098909, WAIT=00:00:59.9901087
2011-02-18 11:52:11,589 [10] DEBUG MEASURE, 00:00:00.0110673, WAIT=00:00:59.9889323
2011-02-18 11:53:11,589 [10] DEBUG MEASURE, 00:00:00.0120986, WAIT=00:00:59.9879010



[연관 글]






[최초 등록일: ]
[최종 수정일: 2/18/2011]


비밀번호

댓글 작성자
 



2011-02-18 04시10분
윈도우 운영체제 자체가 RTOS가 아니다 보니, 정확한 시간 구현은 무리가 있을 것입니다. 어떻게 해서든 정밀도를 높이려면 스레드 우선순위를 높인다거나, 아예 DeviceDriver를 하나 제작해서 클록 인터럽트마다 정확하게 이벤트를 보내주는 것을 만들어야 할 것입니다. 그렇게까지 하는 것은 좀 어려울 것 같고. ^^

대신 중간 중간 현재의 시간값을 가지고 보정을 해줘야 하지 않을까 싶은데요. 검색해 보니.. 다음의 글 같은 것도 나오는군요.

C# timer synchronized with Datetime.Now
; http://stackoverflow.com/questions/2996236/c-timer-synchronized-with-datetime-now
정성태
2011-02-18 05시19분
[윤용한] 답변 감사합니다.
아무리 오차를 줄이려해도 0.000481 milliseconds 씩 계속해서 오차가 발생했었는데
검색하던 중에 multimedia timer를 이용한 글을 보고 적용해보니
99.999999% 정확하게 움직이고 있습니다^^.
가끔 0.000001 오차가 생기지만 그 다음 tick callback에서는 보정되어 정확하게 움직입니다.
16:12:15,735 [12] INFO STEP, 87, 01:27
16:13:15,736 [12] INFO STEP, 88, 01:28 *** 오차발생
16:14:15,735 [12] INFO STEP, 89, 01:29 *** 보정됨
16:15:15,735 [12] INFO STEP, 90, 01:30
16:16:15,735 [12] INFO STEP, 91, 01:31
16:17:15,735 [12] INFO STEP, 92, 01:32
16:18:15,735 [12] INFO STEP, 93, 01:33
16:19:15,735 [12] INFO STEP, 94, 01:34
16:20:15,735 [12] INFO STEP, 95, 01:35

The Multimedia Timer for the .NET Framework
http://www.codeproject.com/KB/miscctrl/lescsmultimediatimer.aspx
[guest]
2011-02-20 09시57분
오~~~ 윤용한님 덕분에 새로운 것을 알았군요. ^^ 멀티미디어 타이머가 간간이 게임 프로그래머들 글에서 나오는 것을 읽긴 했었는데, 정확히 어떤 역할을 하는지는 모르고 있었습니다. 그 한 가지 예로 이해가 팍팍~~~ 되는군요. ^^ 너무 너무 감사드립니다. (오늘은 밥을 안 먹어도 배부를 것 같군요. ^^)
정성태

... 31  32  33  34  35  36  37  38  39  40  41  [42]  43  44  45  ...
NoWriterDateCnt.TitleFile(s)
4797김철환1/13/201711567책에 관한 질문입니다 [3]
4796Bere...1/13/201711690++ 후위연산자와 = 을 함께 사용할 때 생성되는 IL 코드 관련... [2]
4795김철환1/11/201712785이벤트 부분을 읽고 있는데 이해가 안되서 질문합니다.. [11]
4794김철환1/10/201710086안녕하세요 c# 6.0 책을 구매한 사람인데요 [3]
4793장준영1/7/201712119안녕하세요 c언어 처음 공부해보는 학생입니다 [4]파일 다운로드1
4792김재영1/4/201713128소스코드 공개 전 성태님의 의견을 듣고싶습니다 [3]
4791C#초보12/28/201612941비동기 소켓 close시 ObjectDisposedException 문제점 질문 있습니다.. [1]
4790미나리12/24/201613177파워포인트 쇼 제어 SimpleHttpServer.cs 작동문제 [4]파일 다운로드1
4789김솔지12/21/201612015프린트 시, 프린트하는 파일의 파일명 구하는 부분에 대해서 질문드립니다. [1]
4788짜두12/19/201611745Visual Studio 2015 에서 msbuild 12 사용 [5]
4787guest12/18/201613542VLC라이브러리에 대해 아시나요? [3]파일 다운로드1
4785Hyou...12/16/201613668WPF 개발 시 MVVM 프레임워크 사용 [2]
4784ds12/15/201610318문의 드립니다. [2]
4783후배12/13/201611918MemoryStream에 관한 질문 입니다. [5]
4782김형민12/6/201610255[ C# 6.0 ] 126p 오타인가요? [6]
4781질문자11/29/201610369ms워드 저장 오류 [1]
4780최진11/28/201614809안녕 하세요 빌드 관련해서 질문드립니다 꾸벅 [4]
4779손니11/28/201611153안녕하세요 질문하다 드려도 될까요 [3]
4778김상호11/25/201610681재귀호출->비재귀호출 [2]파일 다운로드1
4777권오영11/12/201612937아래 질문 상세 소스전체입니다.. [3]
4776권오영11/11/201610845제가 이클립스를 공부중인데..이상한것을 찾았습니다.. [2]
4775이성환11/11/201614308안녕하세요. SnapsToDevicePixels 질문입니다. [5]파일 다운로드1
4774popo11/10/201610923.net SSL통신 관련 질문 드립니다. [1]
4773김상호11/4/201613424재귀함수 반복문 변환 [1]파일 다운로드1
4772자연인10/27/201614413hwpctrl을 사용하는 사이트에서 나와 브라우저를 종료하면 오류메세지가 나옵니다. [1]파일 다운로드1
4771문종훈10/18/201614453.net 소스 질문이 있습니다 [2]
... 31  32  33  34  35  36  37  38  39  40  41  [42]  43  44  45  ...