Tópico C#

Resumo : neste tutorial, você aprenderá como usar a Threadclasse C# para desenvolver programas multithread.

Introdução à classe Thread C#

Começaremos criando um programa simples:

using System.Diagnostics;
using static System.Console;


static void DoWork()
{
    WriteLine("Doing the work...");
    Thread.Sleep(1000);
    WriteLine("done");
}

var watch = Stopwatch.StartNew();

DoWork();
DoWork();


watch.Stop();
WriteLine($"It took {watch.Elapsed.Seconds} second(s) to complete.");Linguagem de código:  C#  ( cs )

Saída:

Doing the work...
done
Doing the work...
done
It took 2 second(s) to complete.Linguagem de código:  C#  ( cs )

Como funciona.

Primeiro, defina o DoWork()método que leva um segundo para ser executado. O DoWork()método usa o Sleep()método estático da Threadclasse para atrasar um segundo.

Segundo, use o Stopwatchobjeto para medir o tempo de execução do programa. O Startnew()método da Stopwatchclasse inicializa um Stopwatchobjeto, redefine o tempo decorrido para zero e começa a medir o tempo.

Terceiro, chame o DoWork()método duas vezes.

Por fim, pare de medir o tempo decorrido e imprima o tempo que levou para ser executado.

Como cada DoWork()método leva um segundo para ser concluído, todo o programa leva cerca de 2 segundos, o que é esperado.

Usando a classe Thread C#

Para tornar o programa acima multithread, você usa a Threadclasse. As etapas para usar a Threadclasse são as seguintes:

Primeiro, crie uma nova instância da Threadclasse e passe um método para seu construtor:

var t = new Thread(method);Linguagem de código:  C#  ( cs )

Segundo, chame o Start()método para iniciar a execução do thread:

t.Start()Linguagem de código:  C#  ( cs )

Terceiro, chame o Join()método para aguardar a conclusão do thread:

t.Join()Linguagem de código:  C#  ( cs )

O exemplo a seguir mostra como usar a Threadclasse para criar um programa multithread:

using System.Diagnostics;
using static System.Console;


static void DoWork()
{
    WriteLine("Doing the work...");
    Thread.Sleep(1000);
    WriteLine("done");
}

var watch = Stopwatch.StartNew();

var t1 = new Thread(DoWork);
var t2 = new Thread(DoWork);


// start both threads
t1.Start();
t2.Start();

// wait for both threads completed
t1.Join();
t2.Join();


watch.Stop();
WriteLine($"It took {watch.Elapsed.Seconds} second(s) to complete.");Linguagem de código:  C#  ( cs )

Saída:

Doing the work...
Doing the work...
done
done
It took 1 second(s) to complete.Linguagem de código:  C#  ( cs )

Neste exemplo, o programa levou apenas um segundo para ser concluído, embora chame o DoWork()método duas vezes. Ou seja, sua velocidade é o dobro em comparação ao programa que utiliza thread única.

Passando argumentos para os threads

Para passar argumentos para threads, você pode:

  • Primeiro, defina um parâmetro com o tipo object no método que será executado pela thread.
  • Segundo, passe o argumento para o Start()método.

Por exemplo:

using System.Diagnostics;
using static System.Console;


static void DoWork(object? arg)
{
    if (arg == null)
    {
        return;
    }

    string message = (string)arg;
    Thread.Sleep(1000);
    WriteLine(message);

}

var watch = Stopwatch.StartNew();

var t1 = new Thread(DoWork);
var t2 = new Thread(DoWork);


// start both threads
t1.Start("Hi");
t2.Start("Bye");

// wait for both threads completed
t1.Join();
t2.Join();


watch.Stop();
WriteLine($"It took {watch.Elapsed.Seconds} second(s) to complete.");Linguagem de código:  C#  ( cs )

Saída:

Hi
Bye
It took 1 second(s) to complete.Linguagem de código:  C#  ( cs )

Alternativamente, você pode passar uma expressão lambda com argumentos para o Threadconstrutor assim:

using System.Diagnostics;
using static System.Console;


static void DoWork(string message)
{
    Thread.Sleep(1000);
    WriteLine(message);

}

var watch = Stopwatch.StartNew();

var t1 = new Thread(() => DoWork("Hi"));
var t2 = new Thread(() => DoWork("Bye"));


// start both threads
t1.Start();
t2.Start();

// wait for both threads completed
t1.Join();
t2.Join();


watch.Stop();
WriteLine($"It took {watch.Elapsed.Seconds} second(s) to complete.");Linguagem de código:  C#  ( cs )

Saída:

Hi
Bye
It took 1 second(s) to complete.Linguagem de código:  C#  ( cs )

Usar uma expressão lambda é a forma preferida de passar argumentos para o thread, pois o método não precisa converter o objeto para o tipo correto antes de processá-lo.

Usos práticos de multithreading C#

O programa a seguir verifica uma lista de sites e exibe seus códigos de status HTTP correspondentes:

using System.Diagnostics;
using static System.Console;

static void CheckHttpStatus(string url)
{
    HttpClient client = new();
    var response = client.GetAsync(url).Result;
    WriteLine($"The HTTP status code of {url} is {response.StatusCode}");

}

List<string> urls = new(){ 
    "https://www.google.com/",
    "https://www.duckduckgo.com/",
    "https://www.yahoo.com/",
};


var watch = Stopwatch.StartNew();

urls.ForEach(url => CheckHttpStatus(url));

watch.Stop();
WriteLine($"It took {watch.Elapsed.Seconds} second(s) to complete.");Linguagem de código:  C#  ( cs )

Saída:

The HTTP status code of https://www.google.com/ is OK
The HTTP status code of https://www.duckduckgo.com/ is OK
The HTTP status code of https://www.yahoo.com/ is OK
It took 3 second(s) to complete.Linguagem de código:  C#  ( cs )

Como funciona.

Primeiro, defina um método estático CheckHttpStatus()que use o HttpClientobjeto para obter o código de status HTTP de uma URL e exibir seu resultado:

static void CheckHttpStatus(string url)
{
    HttpClient client = new();
    var response = client.GetAsync(url).Result;
    WriteLine($"The HTTP status code of {url} is {response.StatusCode}");

}Linguagem de código:  C#  ( cs )

Segundo, defina uma lista de itens URLspara verificar:

List<string> urls = new(){ 
    "https://www.google.com/",
    "https://www.duckduckgo.com/",
    "https://www.yahoo.com/",
};Linguagem de código:  C#  ( cs )

Terceiro, passe cada entrada da URLslista para o CheckHttpStatus()método. Além disso, envolva as chamadas de método dentro de um bloco que usa Stopwatchpara medir o tempo de execução:

var watch = Stopwatch.StartNew();

urls.ForEach(url => CheckHttpStatus(url));

watch.Stop();
WriteLine($"It took {watch.Elapsed.Seconds} second(s) to complete.");Linguagem de código:  C#  ( cs )

Já que o programa trata de solicitações de rede. É ideal para utilizar multithreading para melhorar o desempenho.

O programa a seguir exibe o código de status HTTP de uma lista de URLsmas usa multithreading:

using System;
using System.Diagnostics;
using static System.Console;

static void CheckHttpStatus(string url)
{
    HttpClient client = new();
    var response = client.GetAsync(url).Result;
    WriteLine($"The HTTP status code of {url} is {response.StatusCode}");

}

List<string> urls = new(){ 
    "https://www.google.com/",
    "https://www.duckduckgo.com/",
    "https://www.yahoo.com/",
};
List<Thread> threads = new();

urls.ForEach(url => threads.Add(new Thread(() => CheckHttpStatus(url))));

var watch = Stopwatch.StartNew();

// start the threads
threads.ForEach(thread=> thread.Start());

// wait for all threads to complete
threads.ForEach(thread => thread.Join());

watch.Stop();
WriteLine($"It took {watch.Elapsed.Seconds} second(s) to complete.");Linguagem de código:  C#  ( cs )

Saída:

The HTTP status code of https://www.google.com/ is OK
The HTTP status code of https://www.duckduckgo.com/ is OK
The HTTP status code of https://www.yahoo.com/ is OK
It took 2 second(s) to complete.Linguagem de código:  C#  ( cs )

Resumo

  • Use a Threadclasse para criar um novo tópico.
  • Chame o Start()método para iniciar a execução do thread.
  • Chame o Join()método para aguardar a conclusão do thread.
  • Use expressões lambda para passar argumentos para threads.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *