Sep 30, 2006

O que esta errado com esta código (Parte X)

Infelizmente, por motivo de tempo, já faz algum tempo que não posto neste blog :(. Infelizmente ao postar a última entrada desta série (Oque esta errado com este código?) não inclui um número. Assim sendo, vou atribuir o valor X para o mesmo. Com relação ao post referido, o problema esta relacionado ao acesso de propriedades de controles da UI em uma thread diferente daquela que o componente.

Observe novamente o código abaixo:

Created with colorer-take5 library. Type 'csharp'

0: using System;
1: using System.Windows.Forms;
2: using System.Threading;
3:
4: namespace TestWinForm
5: {
6:     public partial class TestCallBackFromDiferentThread : Form
7:     {
8:         private System.Threading.Thread workerThread;
9:
10:         public TestCallBackFromDiferentThread()
11:         {
12:             InitializeComponent();
13:         }
14:
15:         private void button1_Click(object sender, EventArgs e)
16:         {
17:             ThreadStart ts = new ThreadStart(AddNewLine);
18:             workerThread = new Thread(ts);
19:             workerThread.Start();
20:         }
21:
22:         private void AddNewLine()
23:         {
24:             listBox1.Items.Add(textBox1.Text);
25:         }
26:     }
27: }

Nas linhas # 17 ~ 19 criamos uma thread e iniciamos a execução da mesma; esta thread chama a função AddNewLine() que por sua vez tenta incluir um item em uma listbox. O problema (como explicado aqui) é que o acesso a controles em WinForms não são thread safe automaticamente, ou seja, se duas threads modificarem o estado de um controle simultaneamente o mesmo pode ficar em um estado inconsistente ou mesmo gerar exceções (oque seria melhor que a primeira possibilidade). Crie uma aplicação WinForm, adicionar os controles listbox, textbox e um botão e copie o código acima para o formulário da aplicação. Se você executar esta aplicação a partir do explorer pode lhe parecer que a mesma não possui problema nenhum; ou seja, aparentemente a mesma funcionou. Contudo execute a mesma a partir do Visual Studio; se a opção "enable exception assistence" estiver habilitada uma exceção será gerada quando a thread tentar acessar o listbox na linha 24. Ok, e como solucionar o problema? Simples, usando a propriedade InvokeRequerid do controle... No método AddNewLine(), antes de incluir o item no listbox consulte a propriedade InvokeRequired; se a mesma for true então execute o método Invoke() passando um delegate que irá executar o mesmo método (AddNewLine()).

Veja no exemplo abaixo:

Created with colorer-take5 library. Type 'csharp'

using System;
using System.Windows.Forms;
using System.Threading;

namespace TestWinForm
{
    public partial class TestCallBackFromDiferentThread : Form
    {
        private System.Threading.Thread workerThread;

         public TestCallBackFromDiferentThread()
         {
             InitializeComponent();
         }

         private void button1_Click(object sender, EventArgs e)
         {
             ThreadStart ts = new ThreadStart(AddNewLine);
             workerThread = new Thread(ts);
             workerThread.Start();
         }

         private void AddNewLine()
         {
             if (listBox1.InvokeRequired)
             {
                listbox1.Invoke(new MethodInvoker(AddNewLine));
             }
             else
             {
                listBox1.Items.Add(textBox1.Text);
             }
         }
     }
 }

Você pode encontrar mais informações (em inglês) sobre o assunto aqui.

A partir do próximo post irei iniciar uma série onde em cada post falarei sobre um aplicativo/site que uso com frequência e que acho interessante. Fique atento.

Adriano

Sep 20, 2006

Eficiência dos antivirus gratuitos...

Estou escrevendo este post a partir do Windows Vista RC1; não porque eu pretendia fazer desta forma mas sim porque meu Windows XP foi contaminado com o bagle_ge; e a pobre da minha esposa foi quem sofreu as primeiras consequências :(. Então, enquanto baixo as novas versões da bios, drivers do chipset etc eu aproveitei para escrever este post. Em parte o fato ocorrido foi bom pois não tenho mais dúvida que a qualidade das versões personal de alguns antivirus deixa bastante a desejar; por outro lado este problema também me fez considerar ainda mais passar a utilizar o Windows Vista (RC1) como meu SO primário. Mas para isto antes necessito fazer alguns testes (principalmente com a impressora já que a mesma já completou 7 anos de vida e o fabricante não me parece muito empolgado com a idéia de escrever um driver de 64 bits para a mesma [ps: o Windows reconheceu a impressora mas não sei se a mesma esta funcionando corretamente pois ainda não imprimi nada nela]) Adriano

Sep 6, 2006

Apresentação (novamente)

Este é meu primeiro post neste novo blog :) Antes de mais nada gostaria de dizer que não vou abandonar meu blog antigo (AccessViolation); só mudei para este novo blog para poder usar alguns recursos que ainda estão na versão beta (a que mais me interessou foi a possibilidade de incluir "labels" mas tem muito mais :) Assim que estes recursos estiverem disponíveis para meu blog antigo devo voltar para o mesmo.