๋ฐ˜์‘ํ˜•

์ง€์—ฐ(Delay) ํ•จ์ˆ˜

ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐœ๋ฐœํ•˜๋‹ค ๋ณด๋ฉด ๋‹จ๋ฐœ์„ฑ์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ์Šค๋ ˆ๋“œ ํ•จ์ˆ˜๊ฐ€ ์žˆ๊ณ , ํ”„๋กœ๊ทธ๋žจ์ด ์‹œ์ž‘๋œ ํ›„ ์ข…๋ฃŒ๋˜๊ธฐ ์ง์ „๊นŒ์ง€ ์‹คํ–‰๋˜๋Š” ์Šค๋ ˆ๋“œ ํ•จ์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ›„์ž์˜ ๊ฒฝ์šฐ์—๋Š” ์Šค๋ ˆ๋“œ ํ•จ์ˆ˜ ๋‚ด์— ๋ฐ˜๋ณต๋ฌธ์„ ๋„ฃ์–ด์„œ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ด ๋ฐ˜๋ณต๋ฌธ์— ์ง€์—ฐ(Delay) ํ•จ์ˆ˜๋ฅผ ๋„ฃ์ง€ ์•Š์œผ๋ฉด ๊ณผ๋„ํ•œ ์—ฐ์‚ฐ์œผ๋กœ ์ธํ•ด CPU ๋ถ€ํ•˜๊ฐ€ ์ฆ๊ฐ€ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

CPU ๋ถ€ํ•˜๋ฅผ ๋‚ฎ์ถ”๊ธฐ ์œ„ํ•ด ์Šค๋ ˆ๋“œ ํ•จ์ˆ˜์˜ ๋ฐ˜๋ณต๋ฌธ ์•ˆ์—๋Š” Sleep() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค. ์‚ฌ์‹ค ๊ผญ ์Šค๋ ˆ๋“œ ํ•จ์ˆ˜์˜ ๋ฐ˜๋ณต๋ฌธ์—๋งŒ ํ•ด๋‹นํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ๊ณผ๋„ํ•œ ๋ฐ˜๋ณต๋ฌธ ๋‚ด์—๋Š” ์ง€์—ฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด CPU ๋ถ€ํ•˜๊ฐ€ ๋†’์•„์ง€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ง€์—ฐ์„ ์œ„ํ•œ ํ•จ์ˆ˜๋กœ๋Š” Sleep() ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ AutoResetEvent.WaitOne()๋„ ์žˆ๊ณ  Task.Delay()๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณธ๋ฌธ์—์„œ๋Š” ๊ฐ ์ง€์—ฐ ํ•จ์ˆ˜์— ๋”ฐ๋ฅธ ์ฐจ์ด์ ์„ ์ •๋ฆฌํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

์ง€์—ฐ ํ•จ์ˆ˜์˜ ์ข…๋ฅ˜

1. Thread.Sleep() ํ•จ์ˆ˜

๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜์ด์ฃ . ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์ •๋ง ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ์ธ์ž๋กœ ๋ฐ€๋ฆฌ๋ฏธํ„ฐ ์‹œ๊ฐ„ ๋˜๋Š” TimeSpan ์‹œ๊ฐ„์„ ์ž…๋ ฅํ•˜๋ฉด ํ•ด๋‹น ์‹œ๊ฐ„๋งŒํผ ์ง€์—ฐ๋ฉ๋‹ˆ๋‹ค. 

public static void Sleep (int millisecondsTimeout);

์‚ฌ์šฉ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

using System;
using System.Threading;

class Example
{
    static void Main()
    {
        for (int i = 0; i < 5; i++)
        {
            Console.WriteLine("Sleep for 2 seconds.");
            Thread.Sleep(2000);
        }

        Console.WriteLine("Main thread exits.");
    }
}

/* ์˜ˆ์ œ ์‹คํ–‰ ๊ฒฐ๊ณผ:

Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Main thread exits.
 */

MSDN ๋ฌธ์„œ๋Š” ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.thread.sleep?view=net-7.0 

 

Thread.Sleep ๋ฉ”์„œ๋“œ (System.Threading)

์ง€์ •๋œ ์‹œ๊ฐ„ ๋™์•ˆ ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ ์ผ์‹œ ์ค‘๋‹จํ•ฉ๋‹ˆ๋‹ค.

learn.microsoft.com

2. WaitHandle.WaitOne() ํ•จ์ˆ˜

์ด ํ•จ์ˆ˜๋Š” WaitHandle์ด Set()์ด ๋  ๋•Œ๊นŒ์ง€ ์Šค๋ ˆ๋“œ๋ฅผ ์ฐจ๋‹จํ•˜๋Š” ๋™์ž‘์„ ํ•ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ์ธ์ž๋Š” Sleep() ํ•จ์ˆ˜์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ๋ฐ€๋ฆฌ๋ฏธํ„ฐ ์‹œ๊ฐ„ ๋˜๋Š” TimeSpan ์‹œ๊ฐ„์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋™์ž‘์€ Sleep()๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ํƒ€์ž„์•„์›ƒ ์‹œ๊ฐ„ ๋‚ด์— WaitHandle์ด Set์ด ๋˜๋ฉด, ํƒ€์ž„์•„์›ƒ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

public virtual bool WaitOne ();

์˜ˆ์ œ ์ฝ”๋“œ๋„ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

using System;
using System.Threading;

class WaitOne
{
    static AutoResetEvent autoEvent = new AutoResetEvent(false);

    static void Main()
    {
        Console.WriteLine("Main starting.");

        ThreadPool.QueueUserWorkItem(
            new WaitCallback(WorkMethod), autoEvent);

        // autoEvent๊ฐ€ Set์ด ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆผ
        autoEvent.WaitOne();
        Console.WriteLine("Work method signaled.\nMain ending.");
    }

    static void WorkMethod(object stateInfo) 
    {
        Console.WriteLine("Work starting.");

        //๋žœ๋คํ•œ ์‹œ๊ฐ„ ๋Œ€๊ธฐ
        Thread.Sleep(new Random().Next(100, 2000));

        //๋Œ€๊ธฐ ํ›„ autoEvent๋ฅผ Set ํ•ฉ๋‹ˆ๋‹ค
        Console.WriteLine("Work ending.");
        ((AutoResetEvent)stateInfo).Set();
    }
}

MSDN ๋ฌธ์„œ๋Š” ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.waithandle.waitone?view=net-7.0 

 

WaitHandle.WaitOne ๋ฉ”์„œ๋“œ (System.Threading)

ํ˜„์žฌ WaitHandle์ด(๊ฐ€) ์‹ ํ˜ธ๋ฅผ ๋ฐ›์„ ๋•Œ๊นŒ์ง€ ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค.

learn.microsoft.com

3. Task.Delay() ํ•จ์ˆ˜

์ด ํ•จ์ˆ˜๋Š” ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋กœ, Task์™€ async/await ํ‚ค์›Œ๋“œ์™€ ๊ฐ™์ด ์„ค๋ช…ํ•˜๊ธฐ์—๋Š” ๋‚ด์šฉ์ด ๋„ˆ๋ฌด ๋งŽ์œผ๋ฏ€๋กœ, Delay() ํ•จ์ˆ˜์— ๋Œ€ํ•ด์„œ๋งŒ ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ํ•ด๋‹น ํ•จ์ˆ˜์˜ ํ˜•ํƒœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ธ์ž๋กœ ๋ฐ€๋ฆฌ๋ฏธํ„ฐ ์‹œ๊ฐ„์„ ์ž…๋ ฅํ•˜๋Š” ๊ฒƒ์ด ๋ชจ๋‘ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.

public static System.Threading.Tasks.Task Delay (int millisecondsDelay);

์ฝ”๋“œ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine($"{DateTime.Now.ToString("T")} Wait ์‹œ์ž‘!");
            Task.Delay(5000).Wait();
            Console.WriteLine($"{DateTime.Now.ToString("T")} Wait ์ข…๋ฃŒ!");
        }
    }
}

Task.Delay().Wait()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•ด๋‹น ์ฝ”๋“œ ๋ถ€๋ถ„์—์„œ ์„ค์ •๋œ ์‹œ๊ฐ„๋งŒํผ ์ง€์—ฐ๋ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ํ•จ์ˆ˜์˜ MSDN ๋ฌธ์„œ๋Š” ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.tasks.task.delay?view=net-7.0 

 

Task.Delay ๋ฉ”์„œ๋“œ (System.Threading.Tasks)

์‹œ๊ฐ„ ์ง€์—ฐ ํ›„ ์™„๋ฃŒ๋˜๋Š” ์ž‘์—…์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

learn.microsoft.com

์ •๋ฆฌ

๊ฐ ์ง€์—ฐ ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋ฐ€๋ฆฌ๋ฏธํ„ฐ ์‹œ๊ฐ„์„ ๋„ฃ์–ด ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์ธก๋ฉด์—์„œ๋Š” ๋ชจ๋‘ ๋™์ž‘์ด ๋™์ผํ•ด ๋ณด์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ์–ด๋Š ์ƒํ™ฉ์—์„œ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฑธ๊นŒ์š”?

1. ๋Œ€๋žต์ ์ธ ์‹œ๊ฐ„์œผ๋กœ ์ง€์—ฐํ•˜๊ณ  ์‹ถ์„ ๋•Œ

Sleep() ํ•จ์ˆ˜๋Š” ๋†’์€ ์ •๋ฐ€๋„๋ฅผ ๊ฐ–๊ณ  ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ดˆ ๋‹จ์œ„ ์ด์ƒ์œผ๋กœ ๋Œ€๋žต์ ์ธ ์ง€์—ฐ์ด ํ•„์š”ํ•˜๊ฑฐ๋‚˜ CPU ๋ถ€ํ•˜๋ฅผ ์–ต์ œํ•˜๊ธฐ ์œ„ํ•จ์ด๋ผ๋ฉด Sleep() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

2. ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹œํ€€์Šค์— ๋”ฐ๋ผ ์ง€์—ฐํ•˜๊ณ  ์‹ถ์„ ๋•Œ

์ œ์–ด๋ฅผ ์œ„ํ•œ ์‹œํ€€์Šค ๋ฃจํ”„ ๋‚ด์—์„œ ๋™๊ธฐํ™”๋ฅผ ์œ„ํ•œ ์ง€์—ฐ์ด ํ•„์š”ํ•˜๋‹ค๋ฉด WaitHandle์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์™ธ๋ถ€์—์„œ ์ „๊ธฐ์  ์‹ ํ˜ธ๊ฐ€ ์ž…๋ ฅ๋˜๋ฉด ์Šคํ…Œ์ด์ง€๋ฅผ ์ด๋™ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์„ ๊ฐ€์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ, ์‹œํ€€์Šค ๋ฃจํ”„ ๋‚ด์— Sleep()์„ ์‚ฌ์šฉํ•˜๋ฉด ์ง€์ •๋œ ์‹œ๊ฐ„๋งŒํผ ๋ธ”๋Ÿฌํ‚น ๋˜์–ด ์‘๋‹ต์ด ๋Šฆ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ WaitHandle.WaitOne()์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ด๋ฒคํŠธ๊ฐ€ Set์ด ๋˜์–ด ์ฆ‰๊ฐ ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ก  ์ด ์˜ˆ์‹œ๋„ ์—ฌ๋Ÿฌ ์กฐ๊ฑด์— ๋”ฐ๋ผ ์ ํ•ฉํ•˜๋ƒ๋Š” ๋”ฐ์ ธ๋ด์•ผ ํ•˜์ง€๋งŒ, ๊ธฐ๋ณธ์ ์œผ๋กœ Sleep()๊ณผ WaitHandle ์ค‘ ์–ด๋Š ๊ฒƒ์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ธ์ง€ ํŒ๋‹จํ•˜๋Š” ๊ธฐ์ค€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ  ์ž๋ฃŒ

https://blog.rogatnev.net/posts/2017/10/Sleep-well.html

๋ฐ˜์‘ํ˜•