Como você já deve saber podemos alcançar o paralelismo usando as classes Parallel ou usando o Parallel LINQ e neste artigo vamos usar os recursos do Parallel LINQ para executar uma tarefa em paralelo. |
Muitos computadores
pessoais e estações de trabalho atualmente possuem dois ou quatro núcleos que
permitem que múltiplas threads serem executadas simultaneamente. Para aproveitar
esses recursos de hardware, você pode paralelizar seu código para distribuir o
trabalho entre vários processadores.
No passado, a paralelização exigia uma manipulação de baixo nível das threads e
bloqueios. A partir do Visual Studio 2010 e da NET Framework 4 houve
significativa melhora no suporte à programação paralela pelo fornecimento de um
novo runtime, novos tipos de biblioteca de classe, e novas ferramentas de
diagnóstico.
Esses recursos simplificam o desenvolvimento em paralelo de modo que você pode
escrever código paralelo eficiente, refinado, e escalável em uma linguagem
natural, sem ter que trabalhar diretamente com threads ou com o pool de threads.
A ilustração a seguir fornece uma visão geral de alto nível da arquitetura de
programação paralela na NET Framework 4.
Parallel LINQ também conhecido como PLINQ é uma implementação do processamento paralelo para LINQ to Objects.
Assim o PLINQ, disponível a partir do .NET Framework 4.0, tem a capacidade de realizar consultas usando a computação paralela. Dessa forma podemos realizar uma tarefa com PLINQ de forma que ela seja executada concorrentemente.
PLINQ implementa todos os métodos de extensão de uma consulta LINQ, tendo operadores adicionais para realizar as operações em paralelo. O grau de simultaneidade das consultas PLINQ esta baseado na capacidade do computador que executa a consulta.
Em muitos cenários (não todos) o PLINQ pode proporcionar um aumento significativo na velocidade usando todas as CPUs ou núcleos de CPU disponíveis.
Uma consulta PLINQ pode proporcionar um ganho de desempenho quanto ela realiza operações com uso intensivo da CPU.
Um problema frequente com aplicações Windows Forms ocorre quando tentamos atualizar um controle no formulário a partir de uma thread diferente da thread que criou o controle; nestes casos uma exceção InvalidOperationException é lançada com a mensagem : “Cross-thread operation not valid: Control ‘txtLog’ accessed from a thread other than the thread it was created on.”
Neste artigo vou mostrar um exemplo prático de como usar PLINQ em uma aplicação ASP .NET.
Recursos usados
Criando o Web Site ASP .NET
Abra o Visual Studio 2013 Express for web e clique em New Web Site;
A seguir selecione o template Visual Basic -> Web -> ASP .NET Empty Web Site e informe o nome Usando_Plinq e clique no botão OK;
A seguir clique no menu WEBSITE e em Add New Item;
Selecione o template
Web Form e informe o nome Default.aspx e clique no botão Add;
Selecione a página Default.aspx no modo Design e clique no menu TABLE -> Insert Table;
Vamos criar uma tabela com 2 linhas e 2 colunas. Defina Rows = 2 e Columns = 2 e clique em OK;
A seguir inclua os seguintes controles na página Default.aspx a partir da ToolBox:
ListBox - ID=lbSites AutoPostBack = True
TextBox - ID=txtResultado TextMode = Multiline
Button - ID=btnIncluir
Button - ID=btnExcluir
TextBox - ID=txtUrl
Button - ID=brnPingarParalelo
Defina o seguinte leiaute na página Default.aspx:
Vamos implementar o código em cada um dos dos eventos relacionados com os controles do formulário no arquivo Default.aspx.vb.
Defina o seguinte namespace na página:
1- Botão Incluir - evento Click : Permite incluir um site no ListBox a partir da caixa de texto txtUrl :
Protected Sub btnIncluir_Click(sender As Object, e As EventArgs) Handles btnIncluir.Click
If Not String.IsNullOrEmpty(txtUrl.Text) Then
If IsUrlValida(txtUrl.Text) Then
lbSites.Items.Add(txtUrl.Text)
lblmsg.Text = ""
Else
lblmsg.Text = "Url inválida. Verifique o formato."
End If
End If
End Sub
|
O código acima usa o método IsUrlValida() que verifica se uma Url informada possui um formato válido usando uma expressão Regex. A seguir vemos o código deste método:
Private Function IsUrlValida(url As String) As Boolean
Return Regex.IsMatch(url, "([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?")
End Function
|
2- Botão Excluir - evento Click - Permite excluir um site da lista de sites no ListBox selecionando o site a ser excluído
Protected Sub btnExcluir_Click(sender As Object, e As EventArgs) Handles btnExcluir.Click
If lbSites.SelectedIndex <> -1 Then
If Not String.IsNullOrEmpty(txtUrl.Text) Then
lbSites.Items.RemoveAt(lbSites.SelectedIndex)
lblmsg.Text = "URL excluída com sucesso"
End If
End If
End Sub
|
3- ListBox - lbSites - evento SelectedIndexChanged - Permite selecionar um item do Listbox e exibir o seu valor na caixa de texto txtUrl:
Protected Sub lbSites_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lbSites.SelectedIndexChanged
txtUrl.Text = lbSites.SelectedItem.Value
End Sub
|
4- Button - btnPingarParalelo - evento Click - Aqui criamos uma lista de sites a partir do controle ListBox e executamos a consulta PLinq exibindo o resultado no controle TextBox - txtResultado:
Protected Sub btnPingarParalelo_Click(sender As Object, e As EventArgs) Handles btnPingarParalelo.Click
Dim sites As New List(Of String)
Dim texto As New StringBuilder
lblmsg.Text = ""
For i = 0 To lbSites.Items.Count - 1
sites.Add(lbSites.Items(i).Value)
Next
Dim respostasPing As List(Of PingReply) = TryCast((
From site In sites.AsParallel().WithDegreeOfParallelism(sites.Count) _
Select FazerPing(site)).ToList(), List(Of PingReply))
For Each s In respostasPing.ToList()
texto.Append("URL : " & Convert.ToString(s.Address) & " Tempo : " & Convert.ToString(s.RoundtripTime) & " : " & Convert.ToString(s.Status))
texto.AppendLine()
txtResultado.Text = texto.ToString
Next
End Sub
|
A consulta LINQ parece uma consulta normal mas a diferença é que usamos o método AsParallel() e WithDegreeOfParallelism :
Para realizar o ping em cada URL temos o método FazerPing() cujo código é visto a seguir:
Private Function FazerPing(ByVal site As String) As PingReply Dim p As New Ping() Return p.Send(site) End Function |
Executando o projeto teremos o resultado conforme a figura a seguir:
Pegue o projeto completo aqui: Usando_Plinq.zip
João 4:34 Disse-lhes Jesus: A minha comida é fazer a vontade daquele que me enviou, e completar a sua obra.
Referências: