Executando Tasks em paralelo em aplicações .Net com o SemaphoreSlim
12006 단어 dotnetcsharpbraziliandevsperformance
소개
Neste artigo vamos entender como executar tasks de forma paralela, visualizar possíveis problemas que poderemos causar em nossas aplicações e aprender a utilizar a classe SemaphoreSlim para nos ajudar a gerenciar a execução das tasks.
세나리오
uma aplicação onde será necessário de tempos em tempos processar uma massa de dados relativamente grande (entre 1 mil à 10 mil registros) e para cada registro processado, envá-lo em uma requisição http. Para essa massa de dados poder ser executada em um tempo aceitável será necessário efetuar processamentos em paralelo.
모범 사례
Vamos criar um trecho de codigo simples onde iremos simular o processamento de 10 mil registros de forma paralela:
static void Main(string[] args)
{
var timer = new Stopwatch();
Console.WriteLine($"Início da execução");
timer.Start();
ProcessarMassaDeDados();
timer.Stop();
Console.WriteLine($"Tempo: {timer.Elapsed:m\\:ss\\.fff}");
Console.ReadKey();
}
static void ProcessarMassaDeDados()
{
var listOfTasks = new List<Task>();
for (int i = 0; i < 10000; i++)
{
listOfTasks.Add(ProcessarRegistro());
}
Task.WaitAll(listOfTasks.ToArray());
}
static async Task ProcessarRegistro()
{
var _httpClient = HttpClientFactory.Create();
await _httpClient.GetAsync("http://httpstat.us/200?sleep=1000");
}
Como podemos ver no codigo acima, primeiro criamos uma lista de tasks e adicionamos a task
ProcessarRegistro
10 mil vezes dentro dessa lista, após isso executamos todas elas em paralelo através do Task.WaitAll
Dentro do método ProcessarRegistro
estamos fazendo uma requisição http que demora um segundo para ser executado.Rodando esse trecho de codigo temos o seguinte resultado no meu computador:
Início da execução
Tempo: 1:37.821
Se não executássemos essas task em paralelo, iria levar pelo menos 10 mil segundos (166 minutos) para executar tudo, já que cada requisição dura um segundo.
Olhando esses números o código acima parece nos atender bem, porém esse código só executou bem porque estamos testando em umambiente local, sem nenhuma concorrência para utilizar os recursarsos essedam processadas pela aplicação não é uma boa ideia, facilmente você irá provocar problemas de rede, causar lentidões nos recursos e Impactar todo oambiente.
Então como ganhar velocidade no processamento com paralelismo mas sem causar problemas e lentidões no peripherale?
Conhecendo 클래스 SemaphoreSlim
O .Net possui uma classe chamada
SemaphoreSlim
que limita o número de Threads que podem acessar um recurso (ou vários recursos) 동시 사용 가능.Vamos modificar o nosso codigo e adicionar essa classe para gerenciar as execuções em paralelo:
static void Main(string[] args)
{
var timer = new Stopwatch();
Console.WriteLine($"Início da execução");
timer.Start();
ProcessarMassaDeDadosComSemaforo();
timer.Stop();
Console.WriteLine($"Tempo: {timer.Elapsed:m\\:ss\\.fff}");
Console.ReadKey();
}
static void ProcessarMassaDeDadosComSemaforo()
{
var semaphoreSlim = new SemaphoreSlim(100, 100);
var listOfTasks = new List<Task>();
for (int i = 0; i < 10000; i++)
{
listOfTasks.Add(ProcessarRegistro(semaphoreSlim));
}
Task.WaitAll(listOfTasks.ToArray());
}
static async Task ProcessarRegistro(SemaphoreSlim semaphoreSlim)
{
await semaphoreSlim.WaitAsync();
var _httpClient = HttpClientFactory.Create();
await _httpClient.GetAsync("http://httpstat.us/200?sleep=1000");
semaphoreSlim.Release();
}
Como podemos ver, instanciamos a classe
SemaphoreSlim
e no seu construtor passamos specificivamente o número inicial de solicitações que podem ser executadas executadas simultaneamente e o número máximo de solicitasIsso Significa que após 100 tasks estarem sendo executadas em paralelo, a próxima só será executada quando uma dessas 100 terminarem, limitando semper a no máximo 100 tasks em paralelo.
Obs: No código acima foi usado a quantidade de 100 execuções em paralelo somente como forma de exemplo, o Ideal é você calibrar esse número de acordo com o seu cenário eambiente.
Dentro do método
ProcessarRegistro
usamos o método semaphoreSlim.WaitAsync()
e semaphoreSlim.Release()
, eles que são os responsáveis Respectivamente por fazer a execução aguardar e para liberRodando o codigo com as modificações temos o seguinte resultado no meu computador:
Início da execução
Tempo: 2:23.149
Podemos perceber que o processamento demora um pouco mais porém os recursos doambiente são utilizados de maneira controlada.
결론
제한 사항을 적용할 수 있습니다. A classe SemaphoreSlim pode ser uma boa solução para utilizar esses recursos de maneira controlada.
참조
SemaphoreSlim Class - Microsoft Documentation
Using SemaphoreSlim to Make Parallel HTTP Requests in .NET Core
Understanding Semaphore in .NET Core
Reference
이 문제에 관하여(Executando Tasks em paralelo em aplicações .Net com o SemaphoreSlim), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/marcosbelorio/executando-tasks-em-paralelo-em-aplicacoes-net-com-o-semaphoreslim-4e9n텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)