<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gabriel Leme</title>
    <description>The latest articles on DEV Community by Gabriel Leme (@glemec).</description>
    <link>https://dev.to/glemec</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F689618%2F8ece020b-6b2e-4775-b0d0-d27878e7ced8.jpeg</url>
      <title>DEV Community: Gabriel Leme</title>
      <link>https://dev.to/glemec</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/glemec"/>
    <language>en</language>
    <item>
      <title>CSharp - Entendendo Threads, Tasks e Process</title>
      <dc:creator>Gabriel Leme</dc:creator>
      <pubDate>Tue, 07 Mar 2023 22:40:05 +0000</pubDate>
      <link>https://dev.to/glemec/csharp-entendendo-threads-tasks-e-process-437c</link>
      <guid>https://dev.to/glemec/csharp-entendendo-threads-tasks-e-process-437c</guid>
      <description>&lt;p&gt;Para entender threads e tasks em C# primeiro é importante entender alguns conceitos de computação com múltiplas threads.&lt;br&gt;
Dentro da linguagem esses conceitos se apresentam através de algumas classes, mas não são nada exclusivos de C#, e sim conceitos de processamento em paralelo implementados pelos sistemas operacionais.&lt;/p&gt;

&lt;p&gt;Visão geral:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fHn2q_u0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/63ol2666i4p9ffkwvnok.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fHn2q_u0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/63ol2666i4p9ffkwvnok.png" alt="Visão geral - Process, Threads e Tasks" width="880" height="714"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Process
&lt;/h2&gt;

&lt;p&gt;O process se refere ao programa que está em execução. Quando você inicia uma aplicação, seja ela ASP.NET, Console ou Desktop, um novo process é criado.&lt;br&gt;
O papel do process é separar os recursos utilizados na execução de cada programa e estabelecer "a fronteira" entre cada um, de forma que cada processo só consiga acessar seus próprios recursos.&lt;/p&gt;
&lt;h2&gt;
  
  
  Thread
&lt;/h2&gt;

&lt;p&gt;Uma thread é a menor unidade de processamento, ela possui um conjunto de instruções, uma porção de memória e todas as informações necessárias para executar um trecho de código.&lt;br&gt;
Em um nível mais profundo, uma thread consiste em uma porção da capacidade de processamento da CPU, seus registradores, um conjunto de instruções do programa e uma porção da memória onde estão armazenados os valores necessários para execução da thread.&lt;/p&gt;

&lt;p&gt;Um processo pode iniciar diversas threads, porém, é importante saber que iniciar e finalizar threads é um processo custoso! Por isso, deve ser usado com parcimônia.&lt;/p&gt;
&lt;h2&gt;
  
  
  Mas como isso existe e é utilizado em C#?
&lt;/h2&gt;

&lt;p&gt;Em C# nós temos classes para iniciar e gerenciar novos processos e novas threads, especificamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Diagnostics.Process&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A classe &lt;code&gt;Process&lt;/code&gt; permite iniciar a execução de um novo programa em um processo separado.&lt;br&gt;
Já a classe &lt;code&gt;Thread&lt;/code&gt; permite a criação de uma nova thread dentro do processo em execução atualmente.&lt;/p&gt;
&lt;h2&gt;
  
  
  Threads em C#.
&lt;/h2&gt;

&lt;p&gt;Podemos criar novas threads para realizar processamento em paralelo.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
Vamos supor que eu precise obter um valor do banco de dados, eu posso fazer isso usando uma outra thread.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;valueFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;getFromDbThread&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;valueFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dbService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValueFromDb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;getFromDbThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O código acima cria uma nova thread, atribui à ela uma execução através de um delegate e no trecho &lt;code&gt;getFromDbThread.Start();&lt;/code&gt; a execução é iniciada.&lt;br&gt;
Threads não retornam valores, por isso, antes de iniciar a thread foi necessário criar uma variável que irá armazenar o valor, nesse caso se trata de &lt;code&gt;long? valueFromDb = null;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;No exemplo acima, seria necessário verificar se a variável &lt;code&gt;valueFromDb&lt;/code&gt; já foi preenchida em algum momento para saber se a thread finalizou a execução, ou podemos usar o comando &lt;code&gt;.Join()&lt;/code&gt; para aguardar o fim da execução da thread.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;valueFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;getFromDbThread&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;valueFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dbService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValueFromDb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;getFromDbThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;//faço outras coisas&lt;/span&gt;

&lt;span class="n"&gt;getFromDbThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//Aguardo a thread finalizar a execução.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso seja necessário encadear processamentos, é necessário verificar se o processo anterior finalizou para iniciar uma nova thread.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;valueFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;getFromDbThread&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;valueFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dbService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValueFromDb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;getFromDbThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;getFromDbThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//Aguardo a thread finalizar a execução.&lt;/span&gt;

&lt;span class="c1"&gt;//Inicio outra thread&lt;/span&gt;
&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;anotherValueFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;getFromDbThread&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;anotherValueFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dbService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAnotherValueFromDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valueFromDb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;getFromDbThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;getFromDbThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//Aguardo a thread finalizar a execução.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lidando com exceções em threads
&lt;/h2&gt;

&lt;p&gt;As threads não propagam exceções automaticamente, então, temos que gerenciar isso manualmente também:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;valueFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;getFromDbThread&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;valueFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dbService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValueFromDb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;threadException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;exp&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threadException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;getFromDbThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;getFromDbThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//Aguardo a thread finalizar a execução.&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É necessário criar uma variável que irá receber e exceção e verificar se houve algum problema para propagar o erro.&lt;/p&gt;

&lt;h1&gt;
  
  
  E é aí que entram as Tasks!
&lt;/h1&gt;

&lt;p&gt;Como deu pra perceber, utilizar threads para processamento em paralelo tem muitos pontos negativos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Código muito verboso&lt;/li&gt;
&lt;li&gt;Complicado de gerenciar resultados&lt;/li&gt;
&lt;li&gt;Complicado de lidar com exceções&lt;/li&gt;
&lt;li&gt;Iniciar e finalizar uma nova thread é um processo custoso para o Sistema Operacional&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por causa disso foram criadas as Tasks!&lt;br&gt;
Tasks são uma abstração em cima do conceito de threads, por baixo dos panos elas utilizam threads, mas possuem uma interface muito mais amigável.&lt;/p&gt;

&lt;p&gt;As tasks apresentam diversas vantagens quando comparadas com threads para exeucução em paralelo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Podem retornar valores&lt;/li&gt;
&lt;li&gt;Propagam exceções por padrão&lt;/li&gt;
&lt;li&gt;É muito fácil gerenciar execução em paralelo e encadear várias tasks&lt;/li&gt;
&lt;li&gt;Tasks não iniciam uma nova thread a cada execução pois se utilizam da ThreadPool (falaremos mais disso abaixo)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Retornando valores com tasks
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;valueFromDbTask&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dbService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValueFromDb&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;valueFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;valueFromDbTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O código se torna muito mais limpo e há um ganho de performance considerável.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lidando com exceções
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;valueFromDbTask&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dbService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValueFromDb&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;valueFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;valueFromDbTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AggregateException&lt;/span&gt; &lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InnerExceptions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tasks propagam exceções através do tipo AggragateException, que por sua vez possui uma array de &lt;code&gt;InnerExceptions&lt;/code&gt; que pode ser verificada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encadeando tasks
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;valueFromDbTask&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dbService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValueFromDb&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="n"&gt;valueFromDbTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ContinueWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;anotherTask&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dbService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAnotherValueFromDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valueFromDbTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos usar &lt;code&gt;.ContinueWith()&lt;/code&gt; para continuar uma task com outra e assegurar execução sequencial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Executando diversas tasks paralelamente
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;valueFromDbTask&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dbService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValueFromDb&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;yetAnotherValue&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dbService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetYetAnotherValueFromDb&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WhenAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valueFromDbTask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yetAnotherValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos usar &lt;code&gt;Task.WhenAll()&lt;/code&gt; para executar várias tarefas de forma paralela.&lt;br&gt;
Especialmente útil em casos onde são tarefas facilmente paralelizaveis, como enviar múltiplas requisições para obter dados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mas existe algum cenário onde faça sentido usar Threads ao invés de Tasks?
&lt;/h2&gt;

&lt;p&gt;Para entender isso, é interessante entender como as Tasks funcionam dentro da plataforma .NET.&lt;br&gt;
As tasks são executadas em uma Thread Pool gerenciada (managed thread pool) que consiste em um conjunto de threads que são gerenciadas pelo próprio runtime do .NET.&lt;br&gt;
Essas threads são ótimas para execução de diversas pequenas tarefas ao longo do processamento do programa, no entanto, como existe um número limitado de threads no thread pool, ocupar uma thread por um longo período de tempo pode ser prejudicial à performance do programa.&lt;/p&gt;

&lt;p&gt;Por causa disso &lt;strong&gt;iniciar manualmente Threads é uma opção melhor em casos onde a tarefa será executada por longos períodos de tempo&lt;/strong&gt;, como por exemplo uma tarefa em background que consome itens de uma fila. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;No geral, tasks são a maneira recomendada de de se lidar com execução de tarefas em segundo plano. Elas fornecem um ferramental muito mais poderoso e produzem um código mais enxuto.&lt;br&gt;
Criar threads manualmente é mais interessante para tarefas de longa duração para não comprometer as threads do thread-pool que podem ser usadas para tarefas menores.&lt;/p&gt;




&lt;h3&gt;
  
  
  Disclaimers
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Sobre Async/Await
&lt;/h4&gt;

&lt;p&gt;Async/Await são conceitos levemente diferentes dos tratados nesse artigo. É possível utilizar await para aguardar a execução de uma ou mais tarefas, e o principal efeito de utilizar async/await é que, enquanto o comando aguardado está sendo executado em outra thread, a thread atual fica livre para processar outras requisições.&lt;br&gt;
Async/Await também cria um overhead de processamento/memória, então, do ponto de vista de consumo de recursos, executar tarefas de forma síncrona economiza mais recursos. &lt;strong&gt;Porém&lt;/strong&gt;, utilizar async/await é benéfico pois utiliza melhor os recursos da máquina como um todo.&lt;/p&gt;

&lt;h4&gt;
  
  
  Sobre a diferença entre linguagem e implementação
&lt;/h4&gt;

&lt;p&gt;É importante entender que a linguagem C# é algo separado da implementação. Os conceitos descritos acima só se aplicam à implementação de C# do CLR da Microsoft através da plataforma .NET 7.&lt;/p&gt;

</description>
      <category>csharp</category>
    </item>
  </channel>
</rss>
