비동기로 작업 하던 중 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개의 좋아요
그냥 코드만 보기에는…
비동기 구문으로 사용하기에는 문제가 있는 코드예요. =ㅅ=;;;;
이걸 while 안에서 호출하기 때문에
다른 비동기 구문과 함께 쓰기에는 무리가 있어 보이네요.
위 메서드는
System.Windows.Forms.Application.DoEvents();
가 메시지 펌프를 쏟아부을 동안
Task 로 만들어뒀던 나머지 비동기 구문들을 이어서 실행할 수 있는 방법이 없어요.
또, DoEvents() 로 실행할 윈도 메시지로 인해 그 동안 메인스레드는 다른 일을 못하게 되겠죠.
DoEvents() 를 호출한 스레드가 차단됩니닷… -ㅂ-;;;
요게 @Vincent 님이 말씀하는 내용인데
여기서 일괄처리된다는 의미가 '윈도 메시지들의 일괄 처리’이고 현재 스레드는 차단됩니다.
(다른 트리거된 이벤트는 블럭되지 않고 수행할 수 있지만서도…)
그렇지 않더라도
만약 윈도 메시지가 적거나 없다면 while 을 통해 엄청나게 빠르게 루프를 돌게 되어 스레드 낭비가 발생하면서
그 와중에 다른 작업을 못하는 건 매 한가지이므로 비동기 처리와는 거리가 있는 형태가 됩니다.
어찌되었든 비동기 처리가 되려면
현재 구문을 벗어나 다른 비동기 구문을 수행할 수 있어야하는데
이미 while 을 빠져나올 방법이 없는 코드라 비동기 delay 로 사용하는 것에는 무리가 있어요.
그나마 의미가 있다면 링크된 블로그의 의도처럼 Thread.Sleep() 대신 쓴다면… 정도입니다.
그러니까
Thread.Sleep 처럼,
특정 구간에서 현재 스레드가 더 이상 진행하지 않아야하고,
(요건 비동기와 다른 겁니다. 비동기는 이하 구문은 await 하더라도 다른 구문은 실행해야하죠.)
그 와중에 UI 가 블럭되지 않아야 하며
fire 된 다른 이벤트들은 정상적으로 핸들링되어야할 때… 사용할까 말까… 이지 않을까 싶어욜.
음… 그런 경우가… 흔치는 않을 것 같ㄱ…
4개의 좋아요