Categoria Dicas .NET - Trabalhando com Threads em formulários Windows

Posted by webmaster | .NET |

As operações com acesso a banco de dados geralmente consomem recursos que podem impactar a sua aplicação. Se você tem que exibir um volume muito grande de dados em um formulário Windows usando um DataGridView tem que considerar que a aplicação pode ficar em estado de espera por um certo período de tempo e, isto pode ser um fator indesejável se este período for muito longo.

Uma das maneiras de evitar este efeito indesejável e diminuir o tempo de espera do usuário é usar Threads.

Usando threads você pode executar a consulta contra o banco de dados e preencher o DataGridView em uma linha de execução distinta liberando assim a sua aplicação para realizar outras tarefas ao invés de ficar esperando que a execução da consulta termine e os dados sejam retornados e exibidos no formulário.

Ocorre que os formulários Windows são baseados em um modelo STA - single-threaded apartment; eles podem ser criados em qualquer thread, mas depois que eles foram criados não podem mudar para uma thread diferente, e os métodos dos formulários Windows também não podem ser acessados em outra thread distinta daquela na qual eles foram criados. Isto significa que todos os métodos dos formulários (e os controles criados na mesma thread) devem ser executados na thread que criou o formulário ou controle do formulário.

Se você tentar chamar um método de um formulário windows em uma thread distinta, uma exceção será disparada, e, dependendo de como você implementou o tratamento de exceção no seu código a aplicação pode encerrar. Se você não estiver efetuando um tratamento de exceção será exibida a seguinte mensagem:

An unhandled exception of type ‘System.ArgumentException’ occurred in system.windows.forms.dll

Então para seu próprio bem tenha em mente sempre o seguinte:

“Quando você estiver trabalhando com controles em formulários windows tenha sempre certeza de somente acessar os controles a partir da thread na qual eles foram criados. senão…”

Como usar multithreading em aplicações com formulários windows?

Veja bem, quando você for chamar um método de um controle que esta em um formulário windows fora da thread de origem do controle você tem que executar a chamada na thread de origem (a chamada tem que ser ‘marshalled’) . Existem duas formas de você fazer isto:

De forma assíncrona - Usar o método BeginInvoke que força o método a ser executado na thread que criou o formulário ou controle. Se você usar BeginInvoke a chamada irá retornar imediatamente. Se você precisar obter o valor de retorno de um delegate invocado de forma assíncrona você pode usar o EndInvoke com o IAsyncResult retornado pelo BeginInvoke para esperar até que o delegate invocado assincronamente tenha sido completado.

De forma síncrona - Usar o método Invoke para obter o mesmo efeito. Quando você usar Invoke a thread atual será bloqueada até que o delegate tenha sido executado.

Todos os controles de formulários windows possuem o método Invoke e a propriedade InvokeRequired .

Você usa o método Invoke para fazer com que o controle transfira a chamada para a thread na qual ele foi criado e então executar a tarefa proposta.

A propriedade InvokeRequired retorna um valor true/false (false indica que a thread atual é a thread da fila de mensagem) indicando se quem chamou o método precisa usar o método Invoke quando a chamada é feita a um método do controle. Exemplo de uso:

- No exemplo abaixo eu estou definindo um delegate e estou verificando a propriedade InvokeRequired da caixa de texto para ver se a chamada ao delegate tem origem na thread de origem do controle ou vem de outra thread.

Public Delegate Sub delegando(ByVal texto As String)
Public Sub chamaMetodo(ByVal texto As String)
If TextBox1.InvokeRequired Then
Dim d As New Delegando(AddressOf chamaMetodo)
TextBox1.Invoke(d, texto)
Else
TextBox1.Text = texto
End If
End Sub

Para encerrar utilize sempre estas duas regras de ouro (golden rules)

1- Nunca invoque qualquer método ou propriedade em um controle criado em outra thread sem usar os métodos/propriedades: Invoke, BeginInvoke, EndInvoke or CreateGraphics, e InvokeRequired.

Cada controle esta vinculado a uma thread que executa a sua fila de mensagens. Se você tentar acessar ou alterar qualquer coisa na interface (por exemplo alterar a propriedade Text) a partir de uma thread diferente você corre o risco de travar o seu programa.

2- Nunca execute uma tarefa que vai consumir muito tempo em uma thread de um controle/formulário windows forms.

Se o seu código esta sendo executado em uma thread de controle/formulário nenhum outro código está rodando nesta thread. O que significa que você não irá receber notificações de eventos, seus controles não serão redesenhados, etc. E você terá que esperar que o código termine de ser executado para realizar outras tarefas. Geralmente os programadores VB poderiam ficar tentados a usar uma chamada a Application.DoEvents . Mas isto não é aconselhável.

Categoria Dicas .NET - Utilizando javascript com .NET

Posted by webmaster | .NET |

O ASP.NET foi uma grande revolução no desenvolvimento web, trouxe uma grande produtividade para todo o processo de desenvolvimento.

Mas o ASP.NET não mudou a arquitetura de desenvolvimento web. Assim como o ASP 3, o ASP.NET é uma tecnologia para desenvolvimento no lado do servidor, realizando acesso a dados e gerando o conteúdo a ser enviado para o client.

Mas em um sistema será necessária também a interatividade com o usuário, programando o lado client. Tarefas como exibir uma mensagem popup ou definir o foco de uma caixa apenas podem ser feitas com programação no lado client, o que continua sendo feito com javascript.

A programação javascript não mudou em nada. O que mudou foi a forma como o javascript é gerado em conjunto com a tecnologia do servidor. Torna-se necessário entender adequadamente a relação de execução entre o que está no servidor e o que está no lado client para ser possível gerar o javascript corretamente. Então vamos analisar em detalhes situações em que o javascript seja necessário e como ele pode ser gerado.

Inserindo eventos em webControls

O javaScript permite que façamos a programação de eventos no lado client. Eventos como click, onmouseover, onmouseout, e outros, podem ser programados em diversos objetos da interface web, tal como botões, imagens, links e outros objetos.

Os eventos no javascript são inseridos na forma de atributos das tags. Através da propriedade Atributes podemos ter controle sobre os atributos de tags que serão renderizados no lado client, assim podemos adicionar eventos client aos objetos.

Por exemplo, se desejarmos adicionar um evento onclick em um botão podemos utilizar o seguinte código:

button1.attributes.add(”onclick”,”alert(’Esse botao foi clicado’)”)

Neste exemplo ao clicarmos no botão veremos uma mensagem popup antes que o postBack tipico do botão ocorra, para finalmente rodar o evento click deste botão no servidor.

Cancelamento de um postBack

Conforme característica do próprio javascript, podemos utilizar o evento onclick para cancelar a ocorrência de um postBack, bastando retornar do evento um valor boolean.

Assim podemos, ao invés de fazer uso da função alert, utilizar a função confirm do javascript para gerar uma mensagem de confirmação em botões, por exemplo.

Veja :

Button1.attributes.add(”onclick”,”return confirm(’Tem certeza ?’)”)

Gerando eventos no HTML

Para alguns eventos, podemos inseri-los diretamente na tag ao invés de fazer a inserção através do Attributes.

Mas apenas para alguns eventos. A regra é a seguinte : Se existe um evento de servidor com o mesmo nome então você não pode inserir o evento direto no HTML, pois será interpretado errado, será confundido com o evento do servidor. Por exemplo, o onclick do botão, que no servidor tem o mesmo nome.

Mas se não existe nenhum evento de servidor com o mesmo nome, fique a vontade, insira o evento na tag normalmente, o webcontrol, ao não reconhecer o atributo, renderizará o atributo no client exatamente como estiver e desta forma irá gerar o evento no javascript.

Um exemplo disso são os eventos omouseover e onmouseout no objeto Image, veja como fica, neste exemplo preenchendo a linha de status do browser :

<asp:Image id=”Image1″ runat=”server”
ImageUrl=”SNAG-0002.jpg” onmouseover=”javascript:window.status=’testando 1,2,3′” onmouseout=”javascript:window.status=””></asp:Image>

Utilizando funções JavaScript

Seria por demais desagradável ter que inserir rotinas mais longas em eventos javaScript utilizando apenas a propriedade attributes.

As regras e lógicas de programação javascript, porém, continuam valendo. Assim sendo, ao invés de inserir todo o código através do attributes podemos apenas inserir uma chamada de função através do attributes.

Assim sendo podemos criar funções diretamente no arquivo .ASPX e através do Attributes inserir apenas as chamadas dessas funções.

<script language=javascript>
<!–
function Confirmar()
{
return(window.confirm(”Tem certeza ?”))

}
//–>
</script>

E no CodeBehind :

Button1.attributes.add(”onclick”,”return Confirmar()”)

Gerando javascript para o client

Existem alguns casos em que o código javascript deve ser executado imediatamente no load da página e não em um evento de um objeto específico.

Os dois casos mais comuns são a exibição de uma mensagem popup no client e a definição do foco para um determinado objeto.

Existem 2 métodos na classe page para a geração de código JavaScript, são os seguintes :

RegisterClientScriptBlock : Gera o script imediatamente após a tag form
RegisterStartUpScript : Gera o script imediatamente antes do fechamento da tag form ( </form> )

Essa sutil diferença tem impacto na geração do código client : com o RegisterClientScriptBlock garantimos que o script seja executado tão logo possível, mas deveremos ter cuidado para que o script não faça referência a objetos que ainda nem tiveram suas tags recebidas pelo browser, do contrário o script irá gerar erro.

Já com o RegisterStartUpScript o script será executado apenas depois de todos os objetos terem chegado ao client, justamente devido a posição que o script é inserido na página.

Ambos os métodos recebem 2 parâmetros, o script a ser inserido dentro da página e um parâmetro chamado “key”. O parâmetro key tem por objetivo impedir que um script seja duplicado dentro da página, o que é especialmente importante durante o processo de criação de custom web controls.

Neste parâmetro, key, criamos uma espécie de nome para o script. Assim sendo se por algum motivo a instrução de geração do script for executada mais de uma vez, o ASP.NET se encarrega de ignorar as execuções duplicadas. São casos incomuns quando o script é gerado diretamente na página, mas um recurso fundamental para para a criação de custom web controls.

Exibindo uma mensagem de conclusão :

Me.RegisterClientScriptBlock(”x”, “<script>alert(’Operação concluida !’)</script>”)

Definindo o foco para uma caixa :

Me.RegisterStartupScript(”z”, “<script>document.all.TextBox1.focus()</script>”)

Cuidados com os nomes dos objetos

No exemplo acima utilizamos o nome do objeto - TextBox1 - para poder definir o foco para o objeto. Mas nem sempre o nome que o objeto possui no servidor será o mesmo nome que o objeto possui no client, os nomes poderão ser diferentes especialmente quando o objeto estiver dentro de algum container, tal como uma DataGrid, um Repeater ou outro objeto do gênero.

Para resolver este problema os objetos possuem uma propriedade chamada clientID. Esta propriedade guarda o nome que o objeto terá quando estiver no client. Assim sendo, mudando o código acima, para termos maior segurança com relação ao nome do objeto, o código fica da seguinte forma :

Me.RegisterStartupScript(”z”, “<script>document.all.” & TextBox1.ClientID & “.focus()</script>”)

Também é possível ter expressões de binding dentro de blocos de javascript, quer seja para a tradução do nome de um objeto ou para algum outro objetivo. Veja :

<script language=”javascript”>
<!–
function DefinirFoco()
{
document.all.<%# Textbox1.clientid %>.focus()

}
//–>
</script>

Pode-se então utilizar a instrução Page.DataBind para provocar o processamento da expressão e desta forma gerar o id do objeto na posição correta.

Manipulando janelas com JavaScript

Manipular janelas popup é outro recurso para o qual precisamos utilizar amplamente o javascript.

Em um sistema é frequente a necessidade de criarmos janelas popup modais para perguntarmos informações adicionais ao usuário. Mais uma vez precisamos de javaScript para isso.

É importante destacar que não podemos utilizar response.redirect ou server.transfer e indicar em qual janela ou frame a página será aberta. Os dois primeiros são instruções do servidor e portanto não tem como controlar a atividade no client.

Abrindo um popup

Essa primeira parte é simples. Podemos utilizar o window.open do javascript normalmente. Podemos inseri-lo diretamente no ASPX ou utilizar uma das instruções Register para fazer a geração do script com o window.open

Utilizando uma janela modal

Neste caso a tarefa complica um pouco mais, pois em geral quando utilizamos uma janela modal desejamos uma resposta, um resultado. Assim sendo precisamos realizar uma comunicação entre as janelas utilizando javascript

Vamos supor um WebForm1.aspx chamando em uma janela modal um Webform2.aspx.

<script language=”javascript”>
<!–

function abrirjanela()
{
var ret;
ret=window.showModalDialog(”webform2.aspx”,”",”");
document.all.TextBox1.value=ret;
}
//–>
</script>

Neste exemplo temos uma função abrirjanela que deverá estar no webForm1.aspx. Esta função faz a abertura de uma janela modal, obtem um valor de resposta e atribui esse valor de resposta na TextBox1.

Esta função pode ser disparada de diversas formas diferentes : utilizando um hyperlink, o click de uma imagem, um botão html, enfim, objetos client.

Porém só é justificável usar um objeto de servidor para fazer esse disparo se for necessário realizar algum processamento adicional antes da janela popup. Nesse caso podemos fazer o disparo da função no click de um botão no servidor (não “fazer o disparo”, mas sim gerar o javascript para isso).

Me.RegisterStartupScript(”x”, “<script>abrirjanela()</script>”)

No WebForm2 precisaremos definir o valor de retorno através da propriedade returnValue do objeto window e fechar o form.

<script language=”javascript”>
<!–
function terminou()
{
window.returnValue=document.all.TextBox1.value;
window.close();
}
//–>
</script>

Mais uma vez temos a mesma questão : Só é justificável usar objetos de servidor se houver algum processamento adicional a ser realizado antes do fechamento. A forma de fazer o disparo, neste caso, fica identica a anterior :

Me.RegisterStartupScript(”x”, “<script>terminou()</script>”)

Detalhes adicionais

Funções javaScript podem ser inseridas em arquivos .JS e estes vinculados a página através da própria tag <script>
O trabalho entre frames também precisa ser feito em javascript
Deve-se ter cuidado com o autoPostback, que insere código javascript em alguns eventos do objeto. Se ao mesmo tempo você tentar inserir seu próprio código javascript para o mesmo evento, gerará erro
O evento onSubmit do form é um evento especial, pois todos os webControls podem manipula-lo. Por isso você não deve tentar lidar diretamente com esse evento. Para isso existe um método chamado RegisterOnSubmitStatement que irá controlar o uso do evento OnSubmit por todos os webControls

Por: Dennes Torres (MCAD, MCSD, MCSE, MCDBA)

Categoria Dicas .NET - Preencher Combobox do banco de dados

Posted by webmaster | .NET |

Bom pessoal, vou mostrar como preencher uma combobox utilizando o banco de dados pubs no SQL server, é um passo a passo bem simples.

Requisitos: SQL server 2000, Visual Studio 2003

1 - Iniciar visual studio
2 - Novo projeto
3 - Arratar uma combobox no form
4 - Utilizar esse comando para importar o pacote do sql
5 - Imports system.data.sqlclient
6 - Digitar esse código no form

Dim conn as new sqlconnection
Conn = sqlconnection(“integrated security = true; data soure=NOMEMAQUINA;initial catalog= pubs”)
Conn.open()
Dim reader as sqldatareader
Dim cmd as sqlcommand
cmd = new sqlcommand (“select authors from pubs”,conn)
reader = cmd.executereader

while reader.read
combobox1.items.add(reader.itens(“authors))
end while

conn.close()

Page 1 of 3123»