Task.Delay 와 Thread.Sleep 을 사용할 때 좋은 규칙이 있습니까?
- 구체적으로, 하나가 다른 것보다 효과적이고 효율적일 수 있도록하는 최소값이 있습니까?
- 마지막으로 Task.Delay로 인해 비동기 / 대기 상태 시스템에서 컨텍스트 전환이 발생하므로이를 사용하는 오버 헤드가 있습니까?
Task.Delay 와 Thread.Sleep 을 사용할 때 좋은 규칙이 있습니까?
답변:
Thread.Sleep
현재 스레드를 차단하려는 경우에 사용하십시오 .
Task.Delay
현재 스레드를 차단하지 않고 논리적 지연을 원할 때 사용하십시오 .
이러한 방법에서 효율성이 가장 중요한 문제가되어서는 안됩니다. 실제 실제 사용은 I / O 조작을위한 재시도 타이머로서 밀리 초가 아닌 초 단위입니다.
Thread.Sleep
컨텍스트 전환을 일으키는 현재 스레드를 차단합니다. 스레드 풀을 사용하는 경우 새 스레드가 할당 될 수도 있습니다. 두 가지 작업 모두 상당히 무겁지만 Task.Delay
etc 등이 제공하는 협력적인 멀티 태스킹 은 모든 오버 헤드를 피하고 처리량을 최대화하며 취소를 허용하고 더 깨끗한 코드를 제공하도록 설계되었습니다.
onesi: I would use
동기 메소드 내부에서 대기하는 @LucaCremry Thread.Sleep` 그러나 프로덕션 코드에서는이 작업을 수행하지 않습니다. 내 경험상, Thread.Sleep
내가 본 모든 것은 올바르게 수정해야 할 디자인 문제를 나타냅니다.
가장 큰 차이점 Task.Delay
와는 Thread.Sleep
그가되어 Task.Delay
비동기 적으로 실행하기위한 것입니다. Task.Delay
동기 코드에서 사용하는 것은 의미가 없습니다 . Thread.Sleep
비동기 코드에서 사용하는 것은 매우 나쁜 생각 입니다.
일반적으로 당신은 호출 Task.Delay()
와 await
키워드 :
await Task.Delay(5000);
또는 지연 전에 코드를 실행하려면 다음을 수행하십시오.
var sw = new Stopwatch();
sw.Start();
Task delay = Task.Delay(5000);
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
await delay;
이것이 무엇을 인쇄 할 것 같습니까? 0.0070048 초 동안 실행 await delay
위를 Console.WriteLine
대신 이동하면 5.0020168 초 동안 실행 중으로 인쇄됩니다.
다음과의 차이점을 살펴 보겠습니다 Thread.Sleep
.
class Program
{
static void Main(string[] args)
{
Task delay = asyncTask();
syncCode();
delay.Wait();
Console.ReadLine();
}
static async Task asyncTask()
{
var sw = new Stopwatch();
sw.Start();
Console.WriteLine("async: Starting");
Task delay = Task.Delay(5000);
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
await delay;
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
Console.WriteLine("async: Done");
}
static void syncCode()
{
var sw = new Stopwatch();
sw.Start();
Console.WriteLine("sync: Starting");
Thread.Sleep(5000);
Console.WriteLine("sync: Running for {0} seconds", sw.Elapsed.TotalSeconds);
Console.WriteLine("sync: Done");
}
}
이것이 인쇄 할 내용을 예측해보십시오 ...
비동기 : 비동기 시작
: 0.0070048 초 동안 실행
동기화 :
비동기 시작 : 5.0119008 초 동안 실행
비동기 : 완료
동기화 : 5.0020168 초 동안 실행
동기화 : 완료
또한 Thread.Sleep
훨씬 더 정확하고 ms 정확도는 실제로 문제가되지 Task.Delay
않지만 최소 15-30ms가 걸릴 수 있습니다. 두 함수의 오버 헤드는 ms 정확도와 비교하여 최소입니다 ( Stopwatch
더 정확한 것이 필요하면 클래스 사용 ). Thread.Sleep
여전히 스레드를 묶고 Task.Delay
기다릴 때 다른 작업을 수행하려면 스레드를 해제하십시오.
Thread.Sleep()
다른 곳에서 사용할 수있는 전체 스레드가 소비됩니다. Thread.Sleep ()를 사용하여 많은 작업을 실행하면 모든 스레드 풀 스레드가 소모되고 성능이 심각하게 저하 될 수 있습니다.
async
이 사용되도록 권장되는 메소드 의 관점에서 누락되었습니다 . 기본적으로 Thread.Sleep()
스레드 풀 스레드에서 실행 하는 것은 좋지 않은 아이디어입니다. 결국 TaskCreationOptions.LongRunning
, (추천하지는 않지만) Task.Factory.StartNew()
경로를 갈 때가 있습니다.
await wait
Tasl.Delay
는 시스템 타이머 를 사용합니다. "시스템 클럭은 일정한 속도로"틱 "합니다. 시스템 타이머의 틱 속도는 약 16ms이므로 요청한 모든 지연 시간은 시스템 클럭의 틱 수로 반올림됩니다. 진드기. Task.Delay
docs.microsoft.com/en-us/dotnet/api/… 의 msdn 설명서를 참조하여 아래로 스크롤하여 설명을 표시하십시오.
현재 스레드가 종료되어 사용 Thread.Sleep
하고 실행 중이 면을 얻을 수 있습니다 ThreadAbortException
. 함께 Task.Delay
하면 항상 취소 토큰을 제공하고 우아하게 죽일 수 있습니다. 그게 내가 선택하는 한 가지 이유입니다 Task.Delay
. 참조 http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspx를
또한이 경우 효율성이 가장 중요하지 않다는 데 동의합니다.
await Task.Delay(5000)
. 작업을 죽일 때 얻을 수 TaskCanceledException
있지만 스레드는 여전히 살아 있습니다. 산뜻한! :)
무언가를 추가하고 싶습니다. 실제로 Task.Delay
타이머 기반 대기 메커니즘입니다. 소스 를 보면 Timer
지연을 담당 하는 클래스에 대한 참조를 찾을 수 있습니다. 반면에 Thread.Sleep
실제로는 현재 스레드를 잠자기 상태로 만듭니다. 이렇게하면 하나의 스레드 만 차단하고 낭비하게됩니다. 비동기 프로그래밍 모델에서는 Task.Delay()
약간의 지연 후에 무언가 (계속)를 원할 경우 항상 사용해야 합니다.