Avançar para o conteúdo principal

Concorrência

Na era dos processadores multicore a execução concorrente faz cada fez mais sentido, de que serve ter um processador com 8 núcleos se os nossos programas só correm uma tarefa de cada vez, ocupando assim um só núcleo.

Cada vez mais é necessário pensar os programas como pequenas tarefas e quando possível executar essas tarefas concorrentemente, ou seja, em simultâneo, porquê esperar que o disco guarde os dados quando podemos criar um thread que executa a tarefa sem interromper a interface.

A classe THREAD é, na plataforma .NET, o ponto de partida para a execução concorrente.
Com esta classe é possível definir prioridades de execução, pausar e retomar as threads bem como sincronizar diferentes threads entre si, criando relações de execução entre diferentes processos.



Para criar uma nova thread na plataforma .NET o programador precisa de ter uma classe com um método que não possua parâmetros de entrada e que devolva void, ou seja não devolve nada.
É este método que será executado quando a nova thread for iniciada.

Para este post vamos criar uma interface que deverá demonstrar a execução concorrente de três threads, para isso construimos o único form do nosso programa assim:

Os numericupdown vão servir para indicar o tempo de espera de cada thread, assim o valor máximo é 1000, que corresponde a um segundo. Quanto maior este valor mais lento será o enchimento da barra.

As progressbar devem ter um valor máximo de 100, que é o valor por defeito.
A ideia é que cada progressbar vá enchendo de cada vez que o código da thread completa um ciclo de execução.

Agora a classe das threads:

    class tarefa
    {
        private int tempo;  //tempo de espera por cada ciclo de execução
        public int valor;    //valor actual da thread
        private int valormax;   //valor máximo que interrompe a execução da thread
       
        //construtor
        public tarefa(int tempo, int valormax)
        {
            valor = 1;
            this.tempo = tempo;
            this.valormax = valormax;
        }
        //método onde a execução da thread ocorre
        public void executa()
        {
            while (true)
            {
                Thread.Sleep(tempo);
                valor++;
                if (valor >= valormax) break;  //aqui para o ciclo e a thread "morre"
            }
        }
    }

Um clique no botão Iniciar demo vai executar o seguinte código:

//Esta linha cria um objecto da classe tarefa

            t1 = new tarefa((int)this.numericUpDown1.Value,(int)this.progressBar1.Maximum);
//Esta linha cria uma thread associada ao método executa do objecto
            thr1 = new Thread(new ThreadStart(t1.executa));
//As restantes linhas criam mais dois objectos
            t2 = new tarefa((int)this.numericUpDown2.Value,  (int)this.progressBar2.Maximum);
            thr2 = new Thread(new ThreadStart(t2.executa));
            t3 = new tarefa((int)this.numericUpDown3.Value,  (int)this.progressBar3.Maximum);
            thr3 = new Thread(new ThreadStart(t3.executa));
//Estas linhas iniciam a execução das três threads
            thr1.Start();
            thr2.Start();
            thr3.Start();
            timer1.Enabled = true;

O botão Parar para as três threads:

            thr1.Abort();
            thr2.Abort();
            thr3.Abort();

O botão Pausar/Continuar pausa as threas e remota a sua execução:

            if (this.button3.Text == "Pausar")
            {
                thr1.Suspend();
                thr2.Suspend();
                thr3.Suspend();
                this.button3.Text = "Continuar";
                this.button2.Enabled = false;
            }
            else
            {
                thr1.Resume();
                thr2.Resume();
                thr3.Resume();
                this.button3.Text = "Pausar";
                this.button2.Enabled = true;
            }

O método Suspend coloca a execução em suspenso e o método Resume retoma a execução.

Por fim adicionei um timer para actualizar as progressbar refletindo os valores das threads.

O projecto está aqui.




Comentários

Mensagens populares deste blogue

Encriptar e Desencriptar

Com o .Net podemos facilmente codificar e descodificar mensagens através do namespace Cryptography. Neste post vamos estudar um programa que encripta um texto com base numa palavra passe e posteriormente descodifica a mensagem. Começamos por criar uma função para encriptar: string codifica(string mensagem, string ppasse) {   //este vector vai ficar com a mensagem encriptada   byte [] mensagem_codificada;  //vamos utilizar codificação UTF8   System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();   // Vamos utilizar o algoritmo MD5 para fazer o Hash da palavra passe   MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();   //Agora podemos então fazer o hash da palavra passe   byte[] TDESChave = HashProvider.ComputeHash(UTF8.GetBytes(ppasse));   //De seguida vamos escolher o algoritmo de encriptação   TripleDESCryptoServiceProvider TDESAlgoritmo = new TripleDESCryptoServiceProvider();   //Confi...

Upgrade do Windows Home para Pro sem formatar

 Há algum tempo que tentava fazer o upgrade do meu Windows 10 da versão Home para a versão Pro, mas chegava sempre a um ponto em que me era solicitado para formatar o sistema e não estava para isso. Finalmente conseguinte seguindo estes passos: - seguinte estes passos  utilizei uma das chaves genéricas para o Windows 10 Pro e fui a Settings > Update & Security > Activation > Change the product key; - após inserir uma das chaves o Windows instala as funcionalidades Pro e pede para reiniciar; - agora tem o Windows Pro mas não está ativado, assim fui ao site urcdkeys  onde comprei uma chave para o Windows Pro por menos de €20; - com essa chave voltei a funcionalidade Change the product key e ativei o Windows; - e pronto, Windows Pro ativado sem formatar ou reinstalar. Importante : eu não tenho nada a ver com o site urcdkeys por isso a vossa experiência pode correr de forma diferente da minha.

PONG em Flash AS3.0

Mais um pequeno jogo para demonstrar algumas das funcionalidades do AS3.0. Para este exemplo vamos implementar uma versão do Pong. Para este Pong vamos criar a possibilidade de acelerar a bola com a raqueta e, para tornar o jogo mais difícil, quando se atingir uma determinada pontuação fazemos aparecer uma parede no meio do campo de jogo. O código é muito parecido com o jogo do post anterior, mas um pouco mais complicado. Para controlar a nossa raqueta utilizamos a seguinte função: function teclado(e:KeyboardEvent):void{ dir_j1=0; if (e.keyCode == Keyboard.UP){ if(jogador1.y>0) jogador1.y -=5; dir_j1=-5; } if (e.keyCode == Keyboard.DOWN){ if(jogador1.y<370) jogador1.y +=5; dir_j1=5; } } Agora está mais simples pois só percorremos as linhas, ou seja, a coluna nunca muda. A raqueta que é controlada pelo computador depende do seguinte código: function movepc():void { if (bola.y>jogador2.y) jogador2.y = jogador2.y + velocidade_y; if (bola.y<jogador2.y) joga...