Qual é a diferença entre task e thread?


378

No C # 4.0, temos Tasko espaço para nome System.Threading.Tasks . Qual é a verdadeira diferença entre Threade Task. Fiz um programa de amostra (ajuda obtida do MSDN) para aprender com o

Parallel.Invoke 
Parallel.For 
Parallel.ForEach 

mas tenha muitas dúvidas, pois a ideia não é tão clara.

Inicialmente, procurei no Stackoverflow um tipo de pergunta semelhante, mas pode estar com esse título de pergunta que não consegui obter o mesmo. Se alguém souber que o mesmo tipo de pergunta foi postado aqui anteriormente, por favor, forneça a referência do link.


8
threads executam tarefas
pm100 13/08/2015

Respostas:


314

Uma tarefa é algo que você deseja fazer.

Um encadeamento é um dos muitos possíveis trabalhadores que executam essa tarefa.

Nos termos do .NET 4.0, uma Tarefa representa uma operação assíncrona. Os segmentos são usados ​​para concluir essa operação dividindo o trabalho em pedaços e atribuindo a segmentos separados.


Você poderia fornecer um exemplo rudimentar de threads trabalhando para concluir uma tarefa? Não sei se os threads estão fazendo um trabalho independente entre si ou fazem algum cálculo de trabalho em equipe ?
pensum 18/02

Ambos os cenários são possíveis: em uma situação ideal, os threads fazem um trabalho independente sem a necessidade de sincronizar com outros threads. Na prática, bloqueios são usados ​​para coordenar threads.
Mitch Wheat

451

Em termos de ciência da computação, a Taské um futuro ou uma promessa . (Algumas pessoas usam esses dois termos de maneira sinomizada, outros usam de maneira diferente, ninguém pode concordar com uma definição precisa .) Basicamente, uma Task<T>"promessa" de devolver a você T, mas não agora, querida, estou meio ocupada, por que não você volta mais tarde?

A Threadé uma maneira de cumprir essa promessa. Mas nem todo mundo Taskprecisa de um novinho em folha Thread. (De fato, criar um encadeamento geralmente é indesejável, porque é muito mais caro do que reutilizar um encadeamento existente no conjunto de encadeamentos. Mais sobre isso daqui a pouco.) Se o valor que você está esperando for do sistema de arquivos ou de um banco de dados ou na rede, não há necessidade de um encadeamento ficar aguardando os dados quando ele pode atender a outras solicitações. Em vez disso, eles Taskpodem registrar um retorno de chamada para receber o (s) valor (es) quando estiverem prontos.

Em particular, o Taskque não dizer por que é que leva um longo tempo para retornar o valor. Ele pode ser que ele leva muito tempo para calcular, ou pode que leva um longo tempo para buscar. Somente no primeiro caso você usaria a Threadpara executar a Task. (No .NET, os threads são muito caros, então você geralmente deseja evitá-los o máximo possível e realmente usá-los apenas se desejar executar vários cálculos pesados ​​em várias CPUs. Por exemplo, no Windows, um thread pesa 12 KiByte ( Eu acho que), no Linux, um thread pesa apenas 4 KiByte, em Erlang / BEAM até apenas 400 bytes. No .NET, é 1 MiByte!)


29
Curiosamente, nas versões anteriores da TPL (Task Parallel Library), havia Task e Future <T>. O futuro <T> foi renomeado para Tarefa <T>. :)
Lee Campbell

23
Como você calculou 1 MB para .NET?
Dvallejo 31/12/12

5
@ DanVallejo: Esse número foi mencionado em uma entrevista com a equipe de design da TPL. Não sei dizer quem disse ou qual foi a entrevista, observei isso anos atrás.
Jörg W Mittag

9
@RIPUNJAYTRIPATHI Claro, mas não precisa ser outro encadeamento, pode ser o encadeamento que solicitou o trabalho em primeiro lugar.
precisa

7
O .NET usa apenas threads do Windows no Windows, então o tamanho é o mesmo - por padrão, geralmente 1 MiB de memória virtual para ambos. A memória física é usada conforme necessário em pedaços do tamanho de página (geralmente 64 kiB), o mesmo com código nativo. O tamanho mínimo da pilha de threads depende do sistema operacional - 256 kiB para Vista, por exemplo. No x86 Linux, o padrão geralmente é 2 MiB - novamente, alocado em pedaços do tamanho de página. (simplificação) Erlang usa apenas um encadeamento do sistema por processo, esses 400 bytes se referem a algo semelhante ao .NETs Task.
Luaan 9/06/16

39

Fio

A coisa simples, você provavelmente não precisa usá-lo, provavelmente pode usar uma LongRunningtarefa e aproveitar os benefícios da TPL - Task Parallel Library, incluída no .NET Framework 4 (fevereiro de 2002) e acima (também .NET Testemunho).

Tarefas

Abstração acima dos Threads. Ele usa o conjunto de encadeamentos (a menos que você especifique a tarefa como uma LongRunningoperação, se houver, um novo encadeamento é criado sob o capô para você).

Grupo de discussão

Como o nome sugere: um pool de threads. A estrutura .NET lida com um número limitado de threads para você. Por quê? Porque abrir 100 threads para executar operações caras da CPU em um processador com apenas 8 núcleos definitivamente não é uma boa idéia. A estrutura manterá esse pool para você, reutilizando os threads (não os criando / eliminando a cada operação) e executando alguns deles em paralelo, de forma que sua CPU não seja queimada.

OK, mas quando usar cada um?

Em resumo: sempre use tarefas.

A tarefa é uma abstração, portanto é muito mais fácil de usar. Eu aconselho você a sempre tentar usar tarefas e, se enfrentar algum problema que faça com que você precise lidar com um thread sozinho (provavelmente 1% do tempo), use threads.

MAS esteja ciente de que:

  • Limite de E / S : para operações vinculadas de E / S (chamadas de banco de dados, arquivos de leitura / gravação, chamadas de APIs, etc.), evite usar tarefas normais, use LongRunningtarefas ( ou threads, se necessário ). Como o uso de tarefas levaria a um pool de threads com alguns threads ocupados e muitas outras tarefas aguardando a sua vez de assumir o pool.
  • Limite da CPU : Para operações vinculadas à CPU, use as tarefas normais (que internamente usarão o pool de threads) e seja feliz.

Uma leve correção, um Thread não é uma "coisa simples". Ele é implementado pelo sistema operacional, a maioria das implementações depende de recursos da CPU e do CS, mas não são implementadas pelo hardware.
Tomer W

7

Você pode usar Taskpara especificar o que deseja fazer e depois anexá-lo Taska um Thread. de modo que Taskseria executado naquele recém-criado Threade não no thread da GUI.

Use Taskcom o TaskFactory.StartNew(Action action). Aqui você executa um delegado, portanto, se você não usasse nenhum thread, ele seria executado no mesmo thread (thread da GUI). Se você mencionar um segmento, poderá executá-lo Taskem um segmento diferente. Esse é um trabalho desnecessário, pois você pode executar diretamente o delegado ou anexá-lo a um encadeamento e executar esse delegado nesse encadeamento. Então não use. é apenas desnecessário. Se você pretende otimizar seu software, este é um bom candidato a ser removido.

** Por favor, note que o Actioné a delegate.


6

Além dos pontos acima, seria bom saber que:

  1. Uma tarefa é por padrão uma tarefa em segundo plano. Você não pode ter uma tarefa em primeiro plano. Por outro lado, um encadeamento pode ser em segundo plano ou em primeiro plano (use a propriedade IsBackground para alterar o comportamento).
  2. As tarefas criadas no conjunto de encadeamentos reciclam os encadeamentos, o que ajuda a economizar recursos. Portanto, na maioria dos casos, as tarefas devem ser sua escolha padrão.
  3. Se as operações forem rápidas, é muito melhor usar uma tarefa em vez de encadear. Para operações de execução longa, as tarefas não oferecem muitas vantagens sobre os encadeamentos.

4

Eu costumo usar Taskpara interagir com o WinForms e o trabalhador em segundo plano simples para não congelar a UI. aqui um exemplo quando eu prefiro usarTask

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();
}

a diferença é que você não precisa usar um MethodInvokercódigo mais curto.


4

A tarefa é como uma operação que você deseja executar, o Thread ajuda a gerenciar essas operações por meio de vários nós do processo. A tarefa é uma opção leve, pois o Threading pode levar a um gerenciamento de código complexo.
Sugerimos que você leia sempre o MSDN (o melhor do mundo)

.

Fio


3

Uma tarefa pode ser vista como uma maneira conveniente e fácil de executar algo de forma assíncrona e paralela.

Normalmente, uma tarefa é tudo que você precisa, não me lembro se alguma vez usei um thread para outra coisa que não a experimentação.

Você pode realizar o mesmo com um encadeamento (com muito esforço) como com uma tarefa.

Fio

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

Tarefa

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

Por padrão, uma tarefa usa o Threadpool, que economiza recursos, pois a criação de threads pode ser cara. Você pode ver uma tarefa como uma abstração de nível superior nos threads.

Como este artigo aponta, a tarefa fornece os seguintes recursos avançados sobre o thread.

  • As tarefas são ajustadas para alavancar processadores multicores.

  • Se o sistema tiver várias tarefas, ele utilizará o conjunto de encadeamentos CLR internamente e, portanto, não terá a sobrecarga associada à criação de um encadeamento dedicado usando o Encadeamento. Reduza também o tempo de alternância de contexto entre vários threads.

  • A tarefa pode retornar um resultado. Não há mecanismo direto para retornar o resultado do encadeamento.
  • Aguarde um conjunto de tarefas, sem uma construção de sinalização.

  • Podemos encadear tarefas para executar uma após a outra.

  • Estabeleça um relacionamento pai / filho quando uma tarefa for iniciada a partir de outra tarefa.

  • A exceção da tarefa filho pode se propagar para a tarefa pai.

  • Cancelamento de suporte de tarefa através do uso de tokens de cancelamento.

  • A implementação assíncrona é fácil na tarefa, usando as palavras-chave 'async' e 'waiting'.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.