작업과 스레드 차이
이 질문에는 이미 답변이 있습니다.
- 작업과 스레드의 차이점은 무엇입니까? 답변 7 개
병렬 프로그래밍을 처음 사용합니다. .NET에는 두 가지 클래스가 있습니다 : Task
및 Thread
.
그래서 내 질문은 :
- 그 클래스들 사이의 차이점은 무엇입니까?
- 때 더 사용하는 것입니다
Thread
언제Task
?
Thread
낮은 수준의 개념은 : 당신이 직접 스레드를 시작하는 경우, 당신은 알고 오히려 스레드 풀 등을 실행하기보다는 별도의 스레드 될 것입니다
Task
"어떤 코드를 어디에서 실행해야하는지"를 추상화 한 것 이상의 의미를 지니고 있습니다. 실제로는 "미래의 결과에 대한 약속"입니다. 따라서 몇 가지 다른 예를 들면 다음과 같습니다.
Task.Delay
실제 CPU 시간이 필요하지 않습니다. 미래에 타이머를 설정하는 것과 같습니다.- 에 의해 반환 된 작업은
WebClient.DownloadStringTaskAsync
로컬로 많은 CPU 시간을 소비하지 않습니다. 네트워크 대기 시간이나 원격 작업 (웹 서버에서)에 대부분의 시간을 소비 할 가능성이 높은 결과를 나타냅니다. Task.Run()
실제로 반환 된 작업 은 "이 코드를 개별적으로 실행하기를 원합니다"라고 말합니다. 해당 코드가 실행되는 정확한 스레드는 여러 가지 요소에 따라 다릅니다.
있습니다 Task<T>
추상화 C # 5에서 비동기 지원에 중추적입니다.
일반적으로 가능한 한 더 높은 수준의 추상화를 사용하는 것이 좋습니다. 현대 C # 코드에서는 자신의 스레드를 명시 적으로 시작할 필요가 거의 없습니다.
실
스레드는 자체 스택 및 커널 리소스가있는 실제 OS 수준 스레드를 나타냅니다. (기술적으로 CLR 구현은 대신 섬유를 사용할 수 있지만 기존 CLR은이를 수행하지 않습니다.) 스레드는 최고 수준의 제어를 허용합니다. 스레드를 Abort () 또는 Suspend () 또는 Resume () 할 수 있습니다 (매우 좋지는 않지만) 상태를 관찰 할 수 있으며 스택 크기, 아파트 상태 또는 문화와 같은 스레드 수준 속성을 설정할 수 있습니다.
스레드의 문제점은 OS 스레드가 비싸다는 것입니다. 당신이 가지고있는 각각의 쓰레드는 그 스택을 위해 적은 양의 메모리를 소비하고 쓰레드 사이의 프로세서 컨텍스트 전환으로서 추가적인 CPU 오버 헤드를 추가합니다. 대신 작업이 가능 해짐에 따라 작은 스레드 풀이 코드를 실행하도록하는 것이 좋습니다.
대체 스레드가없는 경우가 있습니다. (디버깅 목적으로) 이름 또는 아파트 상태 (UI를 표시하기 위해)를 지정해야하는 경우 고유 한 스레드를 작성해야합니다 (여러 UI 스레드를 갖는 것은 일반적으로 좋지 않습니다). 또한 단일 스레드가 소유하고 해당 스레드에서만 사용할 수있는 객체를 유지하려면 스레드 인스턴스를 명시 적으로 생성하는 것이 훨씬 쉬워서 사용하려는 코드가 실행 중인지 쉽게 확인할 수 있습니다. 올바른 실에.
ThreadPool
ThreadPool은 CLR에서 유지 관리하는 스레드 풀 주위의 래퍼입니다. ThreadPool은 전혀 제어 할 수 없습니다. 어떤 시점에서 실행할 작업을 제출하고 풀의 크기를 제어 할 수 있지만 다른 것을 설정할 수는 없습니다. 풀이 제출 한 작업을 언제 시작할지 알 수 없습니다.
ThreadPool을 사용하면 너무 많은 스레드를 작성하는 오버 헤드를 피할 수 있습니다. 그러나 너무 많은 장기 실행 태스크를 스레드 풀에 제출하면 작업이 가득 차게되고 나중에 제출 한 작업으로 인해 이전의 장기 실행 항목이 완료 될 때까지 대기 할 수 있습니다. 또한 ThreadPool은 작업 항목이 완료된 시점 (Thread.Join ()과 달리)을 알 수있는 방법이나 결과를 얻는 방법을 제공하지 않습니다. 따라서 ThreadPool은 호출자가 결과를 필요로하지 않는 짧은 작업에 가장 적합합니다.
직무
마지막으로 Task Parallel Library의 Task 클래스는 두 가지 이점을 모두 제공합니다. ThreadPool과 마찬가지로 작업은 자체 OS 스레드를 만들지 않습니다. 대신 작업은 TaskScheduler에 의해 실행됩니다. 기본 스케줄러는 단순히 ThreadPool에서 실행됩니다.
ThreadPool과 달리 Task를 사용하면 완료 시점과 일반 작업을 통해 결과를 반환 할 수도 있습니다. 기존 작업에서 ContinueWith ()를 호출하여 작업이 완료되면 더 많은 코드를 실행하도록 할 수 있습니다 (이미 완료된 경우 즉시 콜백을 실행 함). 작업이 일반적인 경우 ContinueWith ()는 작업 결과를 전달하여 작업을 사용하는 더 많은 코드를 실행할 수 있습니다.
또한 Wait ()를 호출하여 (또는 일반 작업을 위해 Result 속성을 가져와) 작업이 완료 될 때까지 동 기적으로 기다릴 수 있습니다. Thread.Join ()과 마찬가지로 작업이 완료 될 때까지 호출 스레드를 차단합니다. 동 기적으로 작업을 기다리는 것은 일반적으로 나쁜 생각입니다. 호출 스레드가 다른 작업을 수행하는 것을 방지하고 작업이 현재 스레드를 기다리는 경우 (비동기 적으로도) 교착 상태가 발생할 수 있습니다.
작업은 여전히 ThreadPool에서 실행되므로 스레드 풀을 채우고 새 작업을 차단할 수 있으므로 장기 실행 작업에 사용해서는 안됩니다. 대신 Task는 LongRunning 옵션을 제공하여 TaskScheduler가 ThreadPool에서 실행하지 않고 새 스레드를 시작하도록 지시합니다.
Parallel.For * () 메서드, PLINQ, C # 5 Await 및 BCL의 최신 비동기 메서드를 포함한 모든 최신 고급 동시성 API는 모두 Task를 기반으로합니다.
결론
결론은 작업이 거의 항상 최선의 선택이라는 것입니다. 훨씬 강력한 API를 제공하고 OS 스레드 낭비를 피합니다.
최신 코드에서 스레드를 명시 적으로 작성하는 유일한 이유는 스레드 별 옵션을 설정하거나 고유 한 ID를 유지해야하는 영구 스레드를 유지 보수하는 것입니다.
일반적으로 Task는 thread보다 높은 수준의 개념 이라고 들었습니다. 이것이 바로이 문구의 의미입니다.
Abort / ThreadAbortedException을 사용할 수 없습니다. "비즈니스 코드"주기적으로 테스트
token.IsCancellationRequested
플래그 에서 cancel 이벤트를 지원해야합니다 (또한 db와 같이 길거나 시간이 초과되지 않는 연결을 피하십시오. 그렇지 않으면이 플래그를 테스트 할 기회가 없습니다). 비슷한 이유로Thread.Sleep(delay)
호출은 호출로 대체되어야합니다Task.Delay(delay, token)
.작업 에는 스레드
Suspend
및Resume
메서드 기능 이 없습니다 . 작업 인스턴스도 재사용 할 수 없습니다 .그러나 두 가지 새로운 도구가 제공됩니다.
a) 계속
// continuation with ContinueWhenAll - execute the delegate, when ALL // tasks[] had been finished; other option is ContinueWhenAny Task.Factory.ContinueWhenAll( tasks, () => { int answer = tasks[0].Result + tasks[1].Result; Console.WriteLine("The answer is {0}", answer); } );
b) 중첩 / 자식 작업
//StartNew - starts task immediately, parent ends whith child var parent = Task.Factory.StartNew (() => { var child = Task.Factory.StartNew(() => { //... }); }, TaskCreationOptions.AttachedToParent );
따라서 시스템 스레드는 작업에서 완전히 숨겨 지지만 여전히 작업 코드는 콘크리트 시스템 스레드에서 실행됩니다. 시스템 스레드는 작업을위한 리소스이며 , 작업의 병렬 실행에서 여전히 스레드 풀이 있습니다. 스레드가 새 작업을 실행하는 방법에는 여러 가지 전략이있을 수 있습니다. 다른 공유 리소스 TaskScheduler가 이에 관심을 갖 습니다. 몇 가지 문제 TaskScheduler는 일명 1 - 해결은) 작업 및 전환 비용을 최소화 동일한 스레드에서의 conitnuation 실행하는 것을 선호 인라인 실행 ) 2)가 시작된 순서로 작업을 실행 선호 - 일명 PreferFairness 3) 비활성 스레드 간의 작업의보다 효과적인 분배를 "작업 활동에 대한 사전 지식"에 따라-일명일 도둑질 . 중요 : 일반적으로 "비동기"는 "병렬"과 다릅니다. TaskScheduler 옵션을 사용하면 비동기 작업을 하나의 스레드에서 동 기적으로 실행할 수 있습니다. (작업 제외) 병렬 코드 실행 높은 추상화를 표현하는 데 사용할 수 있습니다 :
Parallel.ForEach
,PLINQ
,Dataflow
.작업은 C #을 비동기 / 일명 await를 기능이 통합되어 약속 모델 , 예를 들면 거기가
requestButton.Clicked += async (o, e) => ProcessResponce(await client.RequestAsync(e.ResourceName));
실행client.RequestAsync
UI 스레드를 차단하지 않습니다. 중요 : 후드Clicked
위임 호출에서 절대적으로 규칙적입니다 (모든 스레딩은 컴파일러에 의해 수행됩니다).
그것은 선택하기에 충분합니다. 중단되는 경향이있는 레거시 API 호출의 취소 기능 (예 : 시간 종료없는 연결)을 지원해야하고이 경우 Thread.Abort ()를 지원하거나 다중 스레드 백그라운드 계산을 작성하고 일시 중단 / 재개를 사용하여 스레드 간 전환을 최적화하려는 경우 즉, 병렬 실행을 수동으로 관리한다는 의미입니다. Thread를 유지하십시오. 그렇지 않으면 작업으로 이동하여 그룹을 쉽게 조작하고 언어에 통합하며 개발자의 생산성을 향상시킬 수 있습니다. 작업 병렬 라이브러리 (TPL) .
이 Thread
클래스는 Windows 에서 스레드 를 작성하고 조작하는 데 사용됩니다 .
A Task
는 일부 비동기 작업을 나타내며 작업을 비동기 및 병렬로 실행하기위한 API 집합 인 Task Parallel Library의 일부입니다 .
예전에는 (예를 들어 TPL 이전) Thread
클래스 를 사용하는 것이 백그라운드에서 또는 병렬로 코드를 실행하는 표준 방법 중 하나 였지만 (더 나은 대안은 종종을 사용하는 ThreadPool
것이 었습니다), 이것은 번거롭고 번거로 웠습니다. 몇 가지 단점은 백그라운드에서 작업을 수행하기 위해 완전히 새로운 스레드를 만드는 데 따른 성능 오버 헤드였습니다.
오늘날 작업과 TPL을 사용하면 시스템 리소스를 훨씬 더 효율적으로 사용할 수있는 추상화를 제공하므로 시간의 90 %가 훨씬 더 나은 솔루션입니다. 코드를 실행하는 스레드를 명시 적으로 제어하려는 시나리오가 몇 가지 있다고 생각하지만 일반적으로 비동기식으로 무언가를 실행하려면 첫 번째 호출 포트가 TPL이어야합니다.
참고 URL : https://stackoverflow.com/questions/13429129/task-vs-thread-differences
'development' 카테고리의 다른 글
귀하의 지점은 3 커밋으로 '원산지 / 마스터'보다 앞서 있습니다. (0) | 2020.03.16 |
---|---|
Bash 파일에 문자열이 있는지 테스트하는 방법은 무엇입니까? (0) | 2020.03.16 |
“<:] {%>”수염이있는 웃는 표현은 무엇입니까? (0) | 2020.03.16 |
PHP cURL이 단일 요청으로 응답 헤더와 본문을 검색 할 수 있습니까? (0) | 2020.03.16 |
C #에서 "사용"의 용도는 무엇입니까 (0) | 2020.03.16 |