Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

kelsch.cristiano

Estar no Loop em C# e poder clicar em botão

Mensagens Recomendadas

kelsch.cristiano

Boa noite estou com um problema que pode ser simples para quem já esteja com um conhecimento mais em C# a dúvuda é:

Fiz uma tela em C# que tem dois botões Star e Stop, quando eu clico em Start ele executa esse código abaixo

private void b_Play_Click(object sender, EventArgs e)

{

  FicarEmLoop = true; //Seta o Loop no programa

  lbl_Executando.Visible = true;

  lbl_Parado.Visible = false;

  b_Play.Enabled = false;

  b_Stop.Enabled = true;

      while (FicarEmLoop)

      {

          //EXECUTA MEUS COMANDOS...

      }

}

Só que assim, a qualquer momento eu quero clicar e atualizar a variavel FicarEmLoop com  false quando clicar em Stop, só que o programa não deixa pois está no meio do loop ainda, existe solução para isso?, esse é meu bloco do botão Stop.

private void b_Stop_Click(object sender, EventArgs e)

{

    FicarEmLoop = false; // Para o loop no programa

}

Preciso poder clicar no botão, o que posso fazer?

Abraço a todos


Att Cristiano Kelsch

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
DVD

O problema é simples, o windows forms controlo de aspecto gráfico da plataforma .NET tal como o Swing do java apenas usa uma thread para actualizar o estado da componente gráfica de uma aplicação, ou seja, todos os eventos gerados por acções da parte gráfica são corridos numa só thread, logo se bloqueias essa thread a tua parte gráfica deixa de funcionar.

Sugiro-te o uso da class BackgroundWorker para pores esse teu loop a correr numa outra thread.

Cump<

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
RA

Boas...

Já agora, aproveito também para tirar umas dúvidas e conhecer as vossas opiniões! :-) A utilização do Application.DoEvents() parece-me ser bastante simples, o que é bom. No entanto, o loop continua a ser executado na thread do GUI o que pode levar a que o form fique "congelado" e o botão Stop inacessível.

Eu faria algo como o DVD sugeriu, mas usaria a TheadPool, por achar mais simples. Algo assim:

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

namespace Tests
{
    public partial class Form1 : Form
    {
        private object lockObject = new object();
        private bool isInLoop = true;
        private bool IsInLoop
        {
            get 
            {
                lock (lockObject)
                {
                    return isInLoop;
                }
            }
            set 
            {
                lock (lockObject)
                {
                    isInLoop = value;
                }
            }
        }

        public Form1()
        {
            InitializeComponent();
            btnStop.Enabled = false;
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            btnStop.Enabled = false;
            btnPlay.Enabled = true;
            IsInLoop = false;
        }

        private void btnPlay_Click(object sender, EventArgs e)
        {
            btnPlay.Enabled = false;
            btnStop.Enabled = true;
            IsInLoop = true;
            ThreadPool.QueueUserWorkItem(ExecuteMyAppLogic);            
        }
        
        private void ExecuteMyAppLogic(object state)
        {
            while (IsInLoop)
            {
                // Executar a lógica da aplicação
            }            
        }

    }
}

Cmpts


"Some men see things as they are and say why - I dream things that never were and say why not." - George Bernard Shaw

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
kelsch.cristiano

Teria como me dar uma exemplo utilizando minhas variaveis do meu projeto?

se puder colocar  no código o que cada linha faz agradeço

obrigado.


Att Cristiano Kelsch

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
kelsch.cristiano

Quando eu minimizar minha tela queria que meu programa ficasse no lado do relógio igual a muitos programas e não minimizado na minha barra, tem como?

Vlw.


Att Cristiano Kelsch

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
RA

Boas...

Quanto ao exemplo com o nome das tuas variáveis... Essa é muito simples!  :cheesygrin:  Acho que consegues lá chegar sozinho!  :) De qualquer maneira, neste exemplo, usei nomes como os teus.

O exemplo que aqui coloco também faz aquela coisinha de "ficar ao lado do relógio". Não sei se era bem isto que querias, mas com um bocado de pesquisa acho que consegues fazer o que queres.

Para que este exemplo funcione tens que fazer o seguinte:

[*]Arrasta um componente "NotifyIcon" (Na Toolbox, em Common Controls) para o teu Form.

[*]Tens que associar um ícone ao teu "NotifyIcon". Para isso tens que preencher a propriedade Icon do teu NotifyIcon com um ficheiro .ico válido (no meu teste usei este).

[*]Tens que criar um "handler" para evento Click do "NotifyIcon". O meu é representado pelo método notifyIcon1_Click.

[*]Tens que criar um "handler" para o evento Resize do teu formulário. O meu é representado pelo método Form1_Resize.

Tem atenção aos comentários do código e vai ficando atento ao fórum para o caso de alguém notar uma falha, ou sugerir uma implementação melhor!  :)

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


namespace Tests
{
    public partial class Form1 : Form
    {
        private object lockObject = new object();
        private bool ficarEmLoop = true;
        private bool FicarEmLoop
        {
            get 
            {
                lock (lockObject)
                {
                    return ficarEmLoop;
                }
            }
            set 
            {
                lock (lockObject)
                {
                    ficarEmLoop = value;
                }
            }
        }


        /// <summary>
        /// Inicializa tudo.
        /// </summary>
        public Form1()
        {
            InitializeComponent();
            b_Stop.Enabled = false;
            lbl_Executando.Visible = false;
            lbl_Parado.Visible = true;
        }


        /// <summary>
        /// Handler do evento Click do Botão Stop (b_Stop)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void b_Stop_Click(object sender, EventArgs e)
        {
            FicarEmLoop = false;
            lbl_Executando.Visible = false;
            lbl_Parado.Visible = true;
            b_Stop.Enabled = false;
            b_Play.Enabled = true;            
        }


        /// <summary>
        /// Handler do evento Click do Botão Play (b_Play)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void b_Play_Click(object sender, EventArgs e)
        {
            FicarEmLoop = true; //Seta o Loop no programa
            lbl_Executando.Visible = true;
            lbl_Parado.Visible = false;
            b_Play.Enabled = false;
            b_Stop.Enabled = true;
                        
            // Dar ordem à ThreadPool para adicionar o método
            // ExecutaMeusComandos à sua "lista de execuções" 
            // (que ocorrerão numa outra thread).
            ThreadPool.QueueUserWorkItem(ExecutaMeusComandos);            
        }
        
        /// <summary>
        /// Irá executar os comandos do Loop.
        /// </summary>
        /// <param name="state"></param>
        private void ExecutaMeusComandos(object state)
        {
            while (FicarEmLoop)
            {
                //EXECUTA MEUS COMANDOS...                               
            }            
        }


        /// <summary>
        /// Handler do evento Resise do teu Form.
        /// Este evento é que fará com que o form "fique ao lado do relógio".
        /// Encontrei isto no Google com a seguinte pesquisa: c# minimize to tray
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Resize(object sender, EventArgs e)
        {            
            if (this.WindowState == FormWindowState.Minimized)
            {
                // Quero que o meu icone "que fica no lado do relógio" fique visivel
                notifyIcon1.Visible = true;    
                // Texto e título para colocar no "balão" que aparece quando minimizamos para o tray
                notifyIcon1.BalloonTipText = "Para voltar a ver o formulário clique neste ícone.";
                notifyIcon1.BalloonTipTitle = "O meu programa";
                // Este balão fica visivel durante 1 segundo
                notifyIcon1.ShowBalloonTip(1000);
                
                // Quando minimizo não quero que o formulário apareça na minha barra de tarefas. 
                // Apenas o quero "ao lado do relógio"
                this.ShowInTaskbar = false;
                this.Hide();
            }            
        }


        /// <summary>
        /// Handler do evento Click do ícone do tray (o ícone "que fica no lado do relógio").
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void notifyIcon1_Click(object sender, EventArgs e)
        {
            // Quero que o meu formulário fique visivel.
            this.Show();
            // Quero que a minha janela volte ao estado "normal" -- pois ela tinha sido minimizada
            this.WindowState = FormWindowState.Normal;
            // Quero que o meu icone "que fica no lado do relógio" fique escondido
            this.notifyIcon1.Visible = false; 
        }


    }
}

Qq dúvida sobre interpretação do que eu disse, ou escrevi, não hesites.

Cmpts.


"Some men see things as they are and say why - I dream things that never were and say why not." - George Bernard Shaw

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
kelsch.cristiano

Vlw, a única coisa que não entendi foi esse bloco abaixo.

private bool FicarEmLoop

        {

            get

            {

                lock (lockObject)

                {

                    return ficarEmLoop;

                }

            }

            set

            {

                lock (lockObject)

                {

                    ficarEmLoop = value;

                }

            }

        }

Obrigado.


Att Cristiano Kelsch

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
RA

Boas...

É assim, nesta implementação simples, honestamente, isso é mais um preciosismo do que outra coisa. Isso tem a ver com conceitos programação concorrente e multi-thread. Esse lock garante-te acesso exclusivo à variável "ficarEmLoop": ou estás a ler, ou a escrever. Nunca acontecerá leitura e escrita ao mesmo tempo. Para leres mais sobre o assunto dá aqui um salto: http://www.inteligenciadigital.org/usando-lock-csharp-thread-dotnet/.

Honestamente, se isso te provoca confusão, podes retirar os locks, ou apagar mesmo a propriedade "FicarEmLoop" e usar apenas a "ficarEmLoop". Não estou a ver nenhuma forma deste código poder dar grandes problemas. Eu coloquei esses locks mais por ser uma boa prática proteger dados que são lidos ou escritos em duas Threads diferentes, ou seja, estou a proteger uma "secção crítica".

Cmpts.


"Some men see things as they are and say why - I dream things that never were and say why not." - George Bernard Shaw

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
kelsch.cristiano

Boa tarde pessoal,

Tem como fazer uma interrupção no programa de 0,1 Segundo quando uma variavel X for igual a verdadeiro? não queria utilizar o Thread.Sleep(10);

Obrigado.


Att Cristiano Kelsch

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.