Daniel Solis (우수 도서, btw)가 Illustrated C# 2008을 읽었으며 이벤트에 대해 더 많은 시간을 할애하여 주제에 대한 이해를 높이기로 결정했습니다. 나는 왜 내가 프로그램을 실행할 때마다 다른 결과를보고 있는지, 그리고 내가 이것을 어떻게 배울 수 있는지 이해하려고 노력 중이다.왜 이러한 타이머 이벤트가 일관성없는 시간에 발생합니까?
(소스 코드 아래)이 책의 샘플 코드에는 MyTimerClass
에 System.Timers.Timer
에 가입 한 일정이 있습니다. ClassA와 ClassB의 두 가지 클래스가 있으며 둘 모두 콘솔에 쓰는 이벤트 핸들러 (하나는 정적이지만 다른 하나는 정적 임)가 있습니다. 프로그램의 main
함수에서 해당 클래스의 이벤트 처리기는 MyTimerClass
의 인스턴스에 이벤트에 묶입니다. 다른 함수가 람다 식을 통해 이벤트 멤버에 추가됩니다.
작성자의 코드를 사용한 후에 다른 클래스 인 ClassC
을 추가하기로 결정했습니다. 프로그램의 Main
함수 내에서 이벤트 처리기를 추가하는 대신 MyTimerClass
의 이벤트에 가입 된 ClassC
의 생성자 내에 별도의 MyTimerClass
개체를 만들기로 결정했습니다.
3 회에 걸쳐 4.25 초 동안 코드를 실행했을 때 결과는 항상 다른 순서로 나타납니다. 순서의 Main
기능에서 사건은 항상 ClassA
, ClassB
, 그 후에 동일한 순서로 람다를 호출합니다. 그러나 ClassC
에 대한 다른 이벤트는 항상 완전 무작위 순서로 호출되는 것처럼 보입니다. 또한 첫 번째 그룹의 메소드 호출은 약간 다른 시간을 갖는 것으로 보이지만 후속 그룹은 모두 같은 시간을 갖는 것으로 나타났습니다. 왜 그런가요?
(1) Event 1 - ClassA - 51:259
Event 2 - ClassC - 51:259
(2) Event 1 - ClassB - 51:261
(3) Event 1 - Lambda - 51:262
(1) Event 1 - ClassA - 52:271
(2) Event 1 - ClassB - 52:271
(3) Event 1 - Lambda - 52:271
Event 2 - ClassC - 52:271
(1) Event 1 - ClassA - 53:285
(2) Event 1 - ClassB - 53:285
(3) Event 1 - Lambda - 53:285
Event 2 - ClassC - 53:285
(1) Event 1 - ClassA - 54:299
(2) Event 1 - ClassB - 54:299
(3) Event 1 - Lambda - 54:299
Event 2 - ClassC - 54:299
(1) Event 1 - ClassA - 17:30
Event 2 - ClassC - 17:30
(2) Event 1 - ClassB - 17:32
(3) Event 1 - Lambda - 17:33
(1) Event 1 - ClassA - 18:42
(2) Event 1 - ClassB - 18:42
(3) Event 1 - Lambda - 18:42
Event 2 - ClassC - 18:42
(1) Event 1 - ClassA - 19:56
(2) Event 1 - ClassB - 19:56
(3) Event 1 - Lambda - 19:56
Event 2 - ClassC - 19:56
Event 2 - ClassC - 20:70
(1) Event 1 - ClassA - 20:70
(2) Event 1 - ClassB - 20:70
(3) Event 1 - Lambda - 20:70
(1) Event 1 - ClassA - 45:220
Event 2 - ClassC - 45:221
(2) Event 1 - ClassB - 45:223
(3) Event 1 - Lambda - 45:223
(1) Event 1 - ClassA - 46:232
(2) Event 1 - ClassB - 46:232
(3) Event 1 - Lambda - 46:232
Event 2 - ClassC - 46:232
Event 2 - ClassC - 47:246
(1) Event 1 - ClassA - 47:246
(2) Event 1 - ClassB - 47:246
(3) Event 1 - Lambda - 47:246
(1) Event 1 - ClassA - 48:260
(2) Event 1 - ClassB - 48:260
(3) Event 1 - Lambda - 48:260
Event 2 - ClassC - 48:260
여기에 소스 코드 내 콘솔 응용 프로그램을위한이다 :
class Program
{
static void Main(string[] args)
{
MyTimerClass mc = new MyTimerClass();
ClassA ca = new ClassA();
ClassC cc = new ClassC();
mc.MyElapsed += ca.TimerHandlerA;
mc.MyElapsed += ClassB.TimerHandlerB;
mc.MyElapsed += (obj, e) =>
{
Console.WriteLine("(3) Event 1 - Lambda - {0}:{1}",
System.DateTime.Now.Second,
System.DateTime.Now.Millisecond);
};
Thread.Sleep(4250);
}
}
class ClassA
{
public void TimerHandlerA(Object obj, EventArgs e)
{
Console.WriteLine("(1) Event 1 - ClassA - {0}:{1}",
System.DateTime.Now.Second,
System.DateTime.Now.Millisecond);
}
}
class ClassB
{
public static void TimerHandlerB(Object obj, EventArgs e)
{
Console.WriteLine("(2) Event 1 - ClassB - {0}:{1}",
System.DateTime.Now.Second,
System.DateTime.Now.Millisecond);
}
}
class ClassC
{
public void TimerHandlerC(Object obj, EventArgs e)
{
Console.WriteLine(" Event 2 - ClassC - {0}:{1}",
System.DateTime.Now.Second,
System.DateTime.Now.Millisecond);
}
public ClassC()
{
// This will create a separate MyTimerClass and
// attach ClassC's event handler to mc's event.
MyTimerClass mc = new MyTimerClass();
mc.MyElapsed += TimerHandlerC;
}
}
public class MyTimerClass
{
public event EventHandler MyElapsed;
private void OnOneSecond(Object obj, EventArgs e)
{
if (MyElapsed != null)
MyElapsed(obj, e);
}
private System.Timers.Timer MyPrivateTimer;
public MyTimerClass()
{
MyPrivateTimer = new System.Timers.Timer();
// This will attach the OnOneSecond Event Handler
// to the system timer which will then raise
// MyElapsed.
MyPrivateTimer.Elapsed += OnOneSecond;
// This sets the interval at 1 second.
MyPrivateTimer.Interval = 1000;
// This turns the timer on when the the class
// is instantiated.
MyPrivateTimer.Enabled = true;
}
}
세 가지 질문 :
- 왜이 결과는 매번 다른 어떤 그 일이 원인이된다?
- 결과의 첫 번째 블록에서 시간이 약간 떨어져 있고 후속 블록이 같은 시간을 갖는 이유는 무엇입니까?
- 이 예제에서 무엇을 배워야합니까?
QPC 메서드는 StopWatch 클래스를 통해 .NET에서 제공됩니다. 그러나 궁극적으로 Windows는 사용자 응용 프로그램을위한 "실시간"운영 체제가되도록 설계되지 않았습니다. 정확한 서브 밀리 초 타이밍은 어렵습니다. –
StopWatch 노트에 감사 드리며 Windows에 관한 중요한 점입니다. 그에 따라 내 대답을 업데이트했습니다. –
설명 해 주셔서 감사합니다. 나는 사건이 다른 순서로 시작되는 원인에 관해서 타이밍에 관심이 없다. Russell의 설명에서 벗어난 가장 좋은 점은 하나의 이벤트 처리기를 등록하여 내 코드가 예상대로 실행되도록 보장하는 것입니다. –