작업과 스레드의 차이점은 무엇입니까?


378

C # 4.0 Task에는 System.Threading.Tasks 네임 스페이스가 있습니다. 사이의 진정한 차이는 무엇 ThreadTask. 학습을 위해 샘플 프로그램 (MSDN에서 가져온 도움)을 사용했습니다.

Parallel.Invoke 
Parallel.For 
Parallel.ForEach 

아이디어가 명확하지 않기 때문에 많은 의심이 있습니다.

나는 처음에 비슷한 유형의 질문에 대해 Stackoverflow를 검색했지만이 질문 제목으로 동일하지 않을 수 있습니다. 누구든지 여기에 게시 된 동일한 유형의 질문에 대해 알고 있다면 친절하게 링크를 참조하십시오.


8
스레드 실행 작업
pm100

답변:


314

작업은 당신이 원하는 것입니다.

스레드는 해당 작업을 수행 할 수있는 많은 작업자 중 하나입니다.

.NET 4.0 용어에서 작업 은 비동기 작업을 나타냅니다. 스레드는 작업을 청크로 분할하고 별도의 스레드에 할당하여 해당 작업을 완료하는 데 사용됩니다.


작업을 완료하기 위해 작업하는 스레드의 기초적인 예를 제공 할 수 있습니까? 스레드가 서로 독립적 인 작업을 수행하는지 또는 팀워크 계산 을 수행하는지 모르겠습니다 .
pensum

두 가지 시나리오가 가능합니다. 최적의 상황에서 스레드는 다른 스레드와 동기화 할 필요없이 독립적 인 작업을 수행합니다. 실제로 잠금은 스레드를 조정하는 데 사용됩니다.
미치 밀

451

컴퓨터 과학 용어로, a Task미래 또는 약속 입니다. (어떤 사람들은이 두 단어를 동의어로 사용하고, 어떤 사람들은 다르게 사용하며, 아무도 정확한 정의 에 동의 할 수 없습니다 .) 기본적으로, Task<T>당신을 돌려 주는 "약속" T, 그러나 지금은 아니고 여보, 좀 바빠요. 나중에 다시 오세요?

A Thread는 그 약속을 이행하는 방법입니다. 그러나 모든 사람 Task에게 새로운 브랜드가 필요한 것은 아닙니다 Thread. (실제로 스레드를 작성하는 것은 스레드 풀에서 기존 스레드를 재사용하는 것보다 훨씬 비싸기 때문에 종종 바람직하지 않습니다. 잠시 후에 더 많은 값을 얻으십시오.) 대기중인 값이 파일 시스템 또는 다른 요청을 처리 할 수있을 때 스레드가 앉아서 데이터를 기다릴 필요가 없습니다. 대신, Task준비가되면 값을 받기 위해 콜백을 등록 할 수 있습니다.

특히,는 Task않습니다 하지이유는 그것이 값을 반환하는 등 시간이 오래 걸리는 것입니다. 이 는 계산하는 데 시간이 오래 걸린다, 또는 그것이 가져 오는 데 시간이 오래 걸린다 수 있습니다. 전자의 경우에만 a Thread를 사용하여 a 를 실행합니다 Task. .NET에서는 스레드가 엄청나게 비싸므로 일반적으로 가능한 많은 스레드를 피하고 여러 CPU에서 여러 개의 무거운 계산을 실행하려는 경우에만 실제로 사용합니다. 예를 들어 Windows의 경우 스레드의 무게는 12 KiByte ( 리눅스에서는 스레드의 무게가 4KB, Erlang / BEAM, 심지어 400 바이트에 불과합니다. .NET에서는 1MiByte입니다!)


29
흥미롭게도 TPL (Task Parallel Library)의 초기 미리보기 릴리스에는 Task와 Future <T>가있었습니다. 그런 다음 Future <T>의 이름이 Task <T>로 변경되었습니다. :)
Lee Campbell

23
.NET에 대해 1MB를 어떻게 계산 했습니까?
dvallejo December

5
@ DanVallejo : 그 숫자는 TPL 디자인 팀과의 인터뷰에서 언급되었습니다. 나는 누가 그것을 말했는지 또는 어떤 인터뷰인지 말할 수 없다. 나는 몇 년 전에 보았다.
Jörg W Mittag

9
@RIPUNJAYTRIPATHI 물론, 다른 스레드 일 필요는 없습니다 . 작업을 처음 요청한 스레드 일 수 있습니다.
Chris Pitman 2016 년

7
.NET은 Windows에서 Windows 스레드 만 사용하므로 크기는 동일합니다. 기본적으로 둘 다에 대해 일반적으로 1MiB의 가상 메모리입니다. 실제 메모리는 기본 코드와 동일하게 페이지 크기 청크 (일반적으로 64KB)에 필요에 따라 사용됩니다. 최소 스레드 스택 크기는 예를 들어 Vista의 경우 OS-256 kiB에 따라 다릅니다. x86 Linux에서 기본값은 보통 2MiB입니다. 다시 페이지 크기의 청크로 할당됩니다. (단순화) Erlang은 프로세스 당 하나의 시스템 스레드 만 사용하며 400 바이트는 .NET과 유사한 것을 참조합니다 Task.
Luaan

39

베어 메탈은 아마도 그것을 사용할 필요가 없습니다. 아마도 작업을 사용하고 LongRunning.NET Framework 4 (2002 년 2 월) 이상 (.NET)에 포함 된 TPL-Task Parallel Library의 이점을 활용할 수 있습니다. 핵심).

작업

스레드 위의 추상화. 이 스레드 풀을 사용 (당신이로 작업을 지정하지 않는 LongRunning때문에, 새로운 스레드가 당신을 위해 후드 아래에 생성 된 경우, 작업을).

스레드 풀

이름에서 알 수 있듯이 스레드 풀. .NET 프레임 워크가 제한된 수의 스레드를 처리하고 있습니까? 왜? 코어 수가 8 개인 프로세서에서 비싼 CPU 작업을 실행하기 위해 100 개의 스레드를 여는 것은 좋은 생각이 아닙니다. 프레임 워크는 스레드를 재사용하고 (각 작업마다 스레드를 작성 / 종료하지 않음) CPU를 태우지 않는 방식으로 스레드를 재사용하여이 풀을 유지 관리합니다.

좋아,하지만 언제 사용합니까?

다시 시작 : 항상 작업을 사용하십시오.

작업은 추상화이므로 사용하기가 훨씬 쉽습니다. 나는 항상 작업을 사용하려고 시도하고 문제가 발생하여 직접 스레드를 처리 해야하는 경우 (아마도 1 %) 스레드를 사용하는 것이 좋습니다.

그러나 다음 사항에 유의하십시오.

  • I / O 바운드 : I / O 바운드 작업 (데이터베이스 호출, 읽기 / 쓰기 파일, API 호출 등)의 경우 일반 작업 사용을 피하고 LongRunning작업 ( 필요한 경우 스레드 )을 사용하십시오. 작업을 사용하면 몇 개의 스레드가 사용 중이고 차례를 풀을 기다리는 다른 작업이 많은 스레드 풀이 생길 수 있습니다.
  • CPU 바운드 : CPU 바운드 작업의 경우 내부 작업이 스레드 풀을 사용하는 일반적인 작업 만 사용하면됩니다.

약간의 수정, 스레드는 "베어 메탈"이 아닙니다. 그것은 OS에 의해 구현되며, 대부분의 구현은 CPU 및 CS의 기능을 중계하지만 하드웨어에 의해 구현되지는 않습니다.
Tomer W

7

당신이 사용할 수있는 Task그 첨부 당신이해야 할 작업을 지정 Task로모그래퍼 Thread. 따라서 GUI 스레드 TaskThread아닌 새로 작성된 항목에서 실행됩니다 .

Task와 함께 사용하십시오 TaskFactory.StartNew(Action action). 여기에서는 대리자를 실행하므로 스레드를 사용하지 않으면 동일한 스레드 (GUI 스레드)에서 실행됩니다. 스레드를 언급 Task하면 다른 스레드에서 실행할 수 있습니다 . 이것은 대리자를 직접 실행하거나 해당 대리자를 스레드에 연결하고 해당 스레드에서 해당 대리자를 실행할 수있는 불필요한 작업 원인입니다. 사용하지 마십시오. 그냥 불필요합니다. 소프트웨어를 최적화하려는 경우 제거하는 것이 좋습니다.

** Actiondelegate입니다.


6

위의 사항 외에도 다음 사항을 아는 것이 좋습니다.

  1. 작업은 기본적으로 백그라운드 작업입니다. 포 그라운드 작업을 가질 수 없습니다. 반면 스레드는 배경 또는 전경일 수 있습니다 (동작을 변경하려면 IsBackground 속성을 사용하십시오).
  2. 스레드 풀에서 생성 된 작업은 스레드를 재활용하여 리소스를 절약합니다. 따라서 대부분의 경우 작업이 기본 선택입니다.
  3. 작업이 빠르면 스레드 대신 작업을 사용하는 것이 훨씬 좋습니다. 장시간 실행되는 작업의 경우 작업이 스레드보다 많은 이점을 제공하지 않습니다.

4

나는 보통 TaskWinforms 및 간단한 백그라운드 작업자와 상호 작용하여 UI를 멈추지 않도록합니다. 여기에 내가 선호하는 예가 있습니다.Task

private async void buttonDownload_Click(object sender, EventArgs e)
{
    buttonDownload.Enabled = false;
    await Task.Run(() => {
        using (var client = new WebClient())
        {
            client.DownloadFile("http://example.com/file.mpeg", "file.mpeg");
        }
    })
    buttonDownload.Enabled = true;
}

VS

private void buttonDownload_Click(object sender, EventArgs e)
{
    buttonDownload.Enabled = false;
    Thread t = new Thread(() =>
    {
        using (var client = new WebClient())
        {
            client.DownloadFile("http://example.com/file.mpeg", "file.mpeg");
        }
        this.Invoke((MethodInvoker)delegate()
        {
            buttonDownload.Enabled = true;
        });
    });
    t.IsBackground = true;
    t.Start();
}

차이점은 MethodInvoker더 짧은 코드 를 사용할 필요가 없다는 것 입니다.


4

작업은 수행하려는 작업과 같으며 Thread는 여러 프로세스 노드를 통해 이러한 작업을 관리하는 데 도움이됩니다. 작업은 스레딩과 같은 경량 옵션은 복잡한 코드 관리로 이어질 수 있습니다
내가 (세계 제일)는 항상 MSDN에서 읽을 제안합니다

작업


3

작업은 비동기 적으로 동시에 병렬로 무언가를 실행하는 편리하고 쉬운 방법으로 볼 수 있습니다.

일반적으로 과제는 당신이 필요로하는 것입니다. 실험 이외의 목적으로 스레드를 사용한 적이 있는지 기억할 수 없습니다.

작업을 할 때와 마찬가지로 스레드를 사용하여 많은 작업을 수행 할 수 있습니다.

int result = 0;
Thread thread = new System.Threading.Thread(() => { 
    result = 1; 
});
thread.Start();
thread.Join();
Console.WriteLine(result); //is 1

직무

int result = await Task.Run(() => {
    return 1; 
});
Console.WriteLine(result); //is 1

작업은 기본적으로 스레드 풀을 사용하므로 스레드를 만드는 데 많은 비용이 들기 때문에 리소스가 절약됩니다. 작업은 스레드에 대한 상위 레벨 추상화로 볼 수 있습니다.

이 기사에서 알 수 있듯이 작업은 스레드보다 다음과 같은 강력한 기능을 제공합니다.

  • 멀티 코어 프로세서를 활용하도록 작업이 조정되었습니다.

  • 시스템에 여러 작업이있는 경우 내부적으로 CLR 스레드 풀을 사용하므로 스레드를 사용하여 전용 스레드를 만드는 것과 관련된 오버 헤드가 없습니다. 또한 여러 스레드 간의 컨텍스트 전환 시간을 줄입니다.

  • 작업은 결과를 반환 할 수 있습니다. 스레드에서 결과를 반환하는 직접적인 메커니즘은 없습니다.
  • 신호 구성없이 일련의 작업을 기다립니다.

  • 작업을 서로 연결하여 차례로 실행할 수 있습니다.

  • 한 작업이 다른 작업에서 시작될 때 부모 / 자식 관계를 설정하십시오.

  • 하위 작업 예외는 상위 작업으로 전파 될 수 있습니다.

  • 취소 토큰을 사용하여 작업 지원 취소.

  • 'async'및 'await'키워드를 사용하여 비동기 적으로 구현하는 작업이 쉽습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.