[C#] Forms.Timer vs Threading.Timer

2022. 7. 25. 20:54·Programming/C#

우선 Timer 관련 글들을 살펴보면

 

[ C# ] 세가지 Timer 와 그 차이점

[출처] [C#] 세가지 Timer 와 그 차이점|작성자 코드클럽 blog.naver.com/jjk003/221926047276 특정 작업을 주기적으로 실행하기 위해 흔히 Timer 객체를 사용합니다 정해진 시간 간격으로 변수를 업데이

minineko.tistory.com

 

Forms.Timer 가 Winform 에 '최적화 되었다' 라는 구문이 눈에 띄는데.

이걸 보고 알아서 잘 관리해 주겟거니... 하다가는

함정에 빠지게 된다.

 

 

1. Forms.Timer

 

Why there are 5 Versions of Timer Classes in .NET?

Why are there five timer classes in the .Net framework, namely the following: System.Timers.Timer System.Threading.Timer System.Windows.Forms.Timer System.Web.UI.Timer System.Windows.Threading.

stackoverflow.com

Forms.Timer 는 멀티쓰레드 방식으로 동작하지 않고 UI Thread 와 자원을 공유하여 사용한다.

때문에 Forms.Timer 를 여러개 만들어 구동시켜도 CPU 점유율은 일정이상 올라가지 않는다.

거기에 더해,

UI Thread 를 공유하기에 Forms.Timer 에서 처리하는 작업이 하드하다면

UI 가 갱신되지 않는 문제점이 발생한다.

 

아주 간단한 예제로 이 문제점을 확인할 수 있는데,

 

Timer1, Timer2, Timer3, TextBox1, TextBox2, TextBox3 이다.

 

실행 시켜보면 아마 UI는 먹통이 될것이다.

그리고 CPU 자원 역시

Form1 '응답없음'

 

단일코어만 사용하는 모습을 살펴볼 수 있다.

 

 

2. Threading.Timer

 

 반면 Threading.Timer 는 '새로운 Thread 를 할당한다'

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            StartTimers();
        }

        public void StartTimers()
        {
            timer1 = new System.Threading.Timer(timer1_Tick, null, 0, 100);
            timer2 = new System.Threading.Timer(timer2_Tick, null, 0, 100);
            timer3 = new System.Threading.Timer(timer3_Tick, null, 0, 100);
        }

        System.Threading.Timer timer1;
        System.Threading.Timer timer2;
        System.Threading.Timer timer3;

        private void timer1_Tick(object? garbage)
        {
            ulong sum = 0;

            for(ulong i = 0; i < 999999999; ++i)
            {
                sum += i;
                sum /= 2;
            }

            if(textBox1.InvokeRequired)
            {
                textBox1.Invoke(new Action(() =>
                {
                    textBox1.Text = sum.ToString();
                }));
            }
            else
            {
            	 	textBox1.Text = sum.ToString();
            }
        }

        private void timer2_Tick(object? garbage)
        {
            ulong sum = 0;

            for (ulong i = 0; i < 999999999; ++i)
            {
                sum += i;
                sum /= 2;
            }


            if (textBox2.InvokeRequired)
            {
                textBox2.Invoke(new Action(() =>
                {
                    textBox2.Text = sum.ToString();
                }));
            }
            else
            {
            	 	textBox2.Text = sum.ToString();
            }
        }

        private void timer3_Tick(object? garbage)
        {
            ulong sum = 0;

            for (ulong i = 0; i < 999999999; ++i)
            {
                sum += i;
                sum /= 2;
            }


            if (textBox3.InvokeRequired)
            {
                textBox3.Invoke(new Action(() =>
                {
                    textBox3.Text = sum.ToString();
                }));
            }
            else
            {
            	 	textBox3.Text = sum.ToString();
            }
        }
    }
}

 

위와 같이 간단하게 코드를 수정 해 주면 

 

CPU 사용량은 미쳐 날뛰지만, 놀랍게도 UI Thread 는 멈추지 않는다.

때문에 WinForm 창 크기를 조정 하거나, 타이틀 바를 잡고 마구 흔들어도

전혀 끊김없이 사용이 가능하다.

 

위 for 문 은 100ms 내에 수행하기엔 벅찬 작업 이므로

미처 작업이 끝마치기 전에 100ms 가 지나 다시 새로운 thread 를 생성해 작업을 돌리게 된다.

중단점을 잡아 Debug 해 보면

Pool 내에 여러 Thread 가 생성되어 있음을 확인할 수 있다.

 

 

3. Conclusion

간단한 테스트 용도로는 Forms.Timer 를 사용해도 문제될것이 없지만,

실시간 처리를 해야 한다거나, 여러 Timer 를 운용해야 한다면

반드시 Threading.Timer 를 사용하도록 하자.

 

여담으로 WPF 에서 기본 Timer 로 사용하는 DispatcherTimer 역시 Forms.Timer 와 동작방식이 비슷하다.

저작자표시 비영리 동일조건 (새창열림)

'Programming > C#' 카테고리의 다른 글

[C#] Task, 비동기에 대해  (0) 2023.08.08
MAUI의 미래에 대해  (0) 2023.06.05
[C#] SharedMemory 사용법  (0) 2022.05.12
[C#] UDP Multicast 수신  (0) 2022.04.08
[C#]System.Timers.Timer 사용시 Race Condition  (0) 2021.12.22
'Programming/C#' 카테고리의 다른 글
  • [C#] Task, 비동기에 대해
  • MAUI의 미래에 대해
  • [C#] SharedMemory 사용법
  • [C#] UDP Multicast 수신
Cyp
Cyp
  • Cyp
    Cyp Software Blog
    Cyp
  • 전체
    오늘
    어제
    • Cyp Blog (163)
      • Artificial Intelligence (40)
        • Article (21)
        • Post (2)
        • Basic (14)
        • Preferences (3)
      • Cyber Security (1)
      • Programming (46)
        • C++ (21)
        • C# (19)
        • Python (2)
        • Rust (0)
        • Java (1)
      • Algorithm (17)
        • BACKJOON (15)
      • Operating System (14)
        • WSL (2)
        • Windows (1)
        • Linux (5)
        • Security (3)
      • Tools (26)
        • Docker (3)
        • DataBase (2)
        • SSH (1)
        • Doxygen (2)
        • Etc (17)
      • Miscellaneous (19)
        • Book (2)
        • Hardware (2)
        • Hevel (1)
  • 블로그 메뉴

    • Home
    • Guest Book
  • 공지사항

    • 블로그 업데이트 노트
    • 블로그 운영방침
  • 인기 글

  • 태그

    utf-8 bom
    y-cruncher
    C4819
    UTF-8 without BOM
    Bom
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
Cyp
[C#] Forms.Timer vs Threading.Timer
상단으로

티스토리툴바