직접 구현하는 Delay와 Task.Delay의 차이점이 뭔지 궁금합니다.

비동기로 작업 하던 중 Delay를 줄 일이 생겨서 찾아보니
한 블로그에서는 (C#, Thread.sleep 대신 사용하기 좋은 함수 Delay)

private static DateTime Delay(int MS)
{
    DateTime ThisMoment = DateTime.Now;
    TimeSpan duration = new TimeSpan(0, 0, 0, 0, MS);
    DateTime AfterWards = ThisMoment.Add(duration);
    while (AfterWards >= ThisMoment)
    {
        System.Windows.Forms.Application.DoEvents();

        ThisMoment = DateTime.Now;
    }
    return DateTime.Now;
}

이러한 코드로 Delay 함수를 따로 만들어 주더라고요.
댓글을 보니 Task.Delay라는 기능을 따로 지원을 해 준다라는 말이 있고
그것에 대한 댓글로 성격이 다르다 라며 다른 분이 또 얘기를 하시길래

어떠한 성격적 차이점이 있는지, 제공해주는 Delay 대신 함수를 만들어 사용해야 하는 상황이
따로 존재하는 지에 대해서 질문 드립니다.

2개의 좋아요

제가 보기에는 Task.Delay를 사용하셔도 될 것 같습니다.

Thread.Sleep은 동기방식으로, 스레드가 '차단’됩니다. 이 때 Winform, WPF같은 프레임워크에서 동작하게 되면 윈도우 메세지도 함께 멈추게 되는데 예를 들어, 버튼 위에 마우스를 가져다 놨을 때 hover 이벤트나, Progress bar 같은 윈도우 메세지로 발생되는 UI 가 Freeze (또는 Hang) 에 걸리게 됩니다.

이 때 링크하신 코드에 써있는데 Application.DoEvents() 를 사용하면 쌓여있던 윈도우 메세지들이 호출 할 때마다 한 번 일괄 처리가 됩니다. 이 때 위에 언급한 Progress bar같은게 움직여지는 행위를 하게 됩니다.

이제 async await가 있고 이 방식은 완벽한 비동기를 지향하므로, UI 메세지들이 쌓이지 않고 계속적으로 처리가 이루어 집니다.

따라서 제 의견으론 그냥 await Task.Delay를 사용하셔도 될 것 같습니다.

3개의 좋아요

감사합니다!

2개의 좋아요

그냥 코드만 보기에는…
비동기 구문으로 사용하기에는 문제가 있는 코드예요. =ㅅ=;;;;

이걸 while 안에서 호출하기 때문에
다른 비동기 구문과 함께 쓰기에는 무리가 있어 보이네요.

위 메서드는
System.Windows.Forms.Application.DoEvents(); 가 메시지 펌프를 쏟아부을 동안
Task 로 만들어뒀던 나머지 비동기 구문들을 이어서 실행할 수 있는 방법이 없어요.
또, DoEvents() 로 실행할 윈도 메시지로 인해 그 동안 메인스레드는 다른 일을 못하게 되겠죠.
DoEvents() 를 호출한 스레드가 차단됩니닷… -ㅂ-;;;
요게 @Vincent 님이 말씀하는 내용인데
여기서 일괄처리된다는 의미가 '윈도 메시지들의 일괄 처리’이고 현재 스레드는 차단됩니다.
(다른 트리거된 이벤트는 블럭되지 않고 수행할 수 있지만서도…)

그렇지 않더라도
만약 윈도 메시지가 적거나 없다면 while 을 통해 엄청나게 빠르게 루프를 돌게 되어 스레드 낭비가 발생하면서
그 와중에 다른 작업을 못하는 건 매 한가지이므로 비동기 처리와는 거리가 있는 형태가 됩니다.

어찌되었든 비동기 처리가 되려면
현재 구문을 벗어나 다른 비동기 구문을 수행할 수 있어야하는데
이미 while 을 빠져나올 방법이 없는 코드라 비동기 delay 로 사용하는 것에는 무리가 있어요.

그나마 의미가 있다면 링크된 블로그의 의도처럼 Thread.Sleep() 대신 쓴다면… 정도입니다.

그러니까
Thread.Sleep 처럼,
특정 구간에서 현재 스레드가 더 이상 진행하지 않아야하고,
(요건 비동기와 다른 겁니다. 비동기는 이하 구문은 await 하더라도 다른 구문은 실행해야하죠.)

그 와중에 UI 가 블럭되지 않아야 하며
fire 된 다른 이벤트들은 정상적으로 핸들링되어야할 때… 사용할까 말까… 이지 않을까 싶어욜.

음… 그런 경우가… 흔치는 않을 것 같ㄱ…

4개의 좋아요

오~ 자세한 부연설명 감사드립니다!!

1개의 좋아요