none
OOP - C# dúvida RRS feed

  • Pergunta

  • Olá, Estou com o seguinte problema;

    Tenho escrevi três métodos

    verificaTempo()

    Varre a tabela e compara alguns valores, se o resultado for verdadeiro chama o método startCronometro(id) passando o do resultado da busca.

    startCronometro()

    basicamente realiza um inner join em algumas tabelas passa os valores por parâmetro para o cronometrar();

    cronometrar()

    só realiza os decremento de alguns número que foram recuperados e atualiza o banco.

    O problema que estou tendo é que como a busca na tabela é contínua, ao ocorrer o primeiro resultado verdadeiro da busca, o cronometro é iniciado, e a busca volta a ocorrer. Se nesse momento, ocorrer mais um resultado verdadeiro(no caso de um evento no mesmo intervalo de tempo do primeiro evento, que já esta rodando) O primeiro evento para e inicia o segundo. Isso não pode acontecer!. Isso está ocorrendo pq eu só tenho um método cronometrar, e ao receber o novo id, ele substitui os valores. O resultado é que não consigo ter dois eventos sendo cronometrados ao mesmo tempo.

    Estava pensando se existe alguma maneira de resolver isso, talvez reescrevendo o métodos cronometrar(). Acho que OOP resolveria isso, mas estou tendo dificuldades.

    grato

     




    segunda-feira, 22 de agosto de 2011 19:03

Respostas

  • Opa..bom dia...que bom q está dando certo...

    Sobre não estar sendo chamado é pq faltou esse cara...bkgFila.RunWorkerAsync(); Essa chamada é que dará o start no evento da Thread....

    Outra dica....dentro dessa chamada vc poderá passar parametros e depois pegar o valor desse parâmetro dentro do evento da Thread....seguindo o mesmo exemplo do seu código:

     

            // Essa parte será chamada quantas vezes quiser....dentro de qualquer função ou evento... 
            BackgroundWorker bkgfila = new BackgroundWorker(); 
            bkgfila.DoWork += new DoWorkEventHandler(bkgfila_DoWork); 
            bkgFila.RunWorkerAsync(idCronometro); 
            
            // Esse evento ele terá uma unica vez...pois o parametro passado será dinamico... 
            private void bkgfila_DoWork(object sender, DoWorkEventArgs e) 
            { 
                startCronometro(Convert.ToInt32(e.Argument)); 
            }
    
    Ref. ao limite de execuções...realmente não há...o limite será a máquina.....mas você poderá montar um controle ...pra limitar...sem problemas.... 
    Bom, tenho um serviço q roda em um servidor na empresa que trabalho, ele está sem limites de Threads...já acompanhei 20 Threads executando normalmente ao mesmo tempo sem problemas... :)
    Gustavo Gouveia..

     


    terça-feira, 23 de agosto de 2011 10:39

Todas as Respostas

  • Acredito que estou precisando é usar alguma coisa do tipo método dinâmico. Cada id que for sendo encontrado é gerado dinamicamente um método único para ele, sem precisar parar o método que está sendo executado. Qual o nome técnico para isso em C#, para que eu possa me aprofundar no assunto?

    grato

     




    segunda-feira, 22 de agosto de 2011 19:49
  • Marcelo...Boa tarde...

     

    Pelo q entendi vc precisa startar uma Thread !?!? 

     

    Se for isso o cara q você vai precisar é o BackgroundWorker...Segue um exemplo de como criar ele dinâmico...

    Forma de criar o objeto...atribuindo o evento ao mesmo...

     

                        // Criando uma thread
                        BackgroundWorker bkwFila = new BackgroundWorker();
                        bkwFila.DoWork += new DoWorkEventHandler(ExecutaThread);
                        bkwFila.RunWorkerAsync();
    

     

    Código dentro do evendo da thread

     

            private void ExecutaThread(object sender, System.ComponentModel.DoWorkEventArgs e)
            { 
            } 

     

     

    Espero ter ajudado..

    Gustavo Gouveia...

    • Marcado como Resposta Marcello Azevedo segunda-feira, 22 de agosto de 2011 20:36
    • Não Marcado como Resposta Marcello Azevedo segunda-feira, 22 de agosto de 2011 20:52
    • Marcado como Resposta Marcello Azevedo segunda-feira, 22 de agosto de 2011 20:56
    • Não Marcado como Resposta Marcello Azevedo segunda-feira, 22 de agosto de 2011 20:57
    • Marcado como Resposta Marcello Azevedo segunda-feira, 22 de agosto de 2011 20:57
    • Não Marcado como Resposta Marcello Azevedo segunda-feira, 22 de agosto de 2011 20:57
    • Não Marcado como Resposta Marcello Azevedo segunda-feira, 22 de agosto de 2011 20:57
    • Não Marcado como Resposta Marcello Azevedo segunda-feira, 22 de agosto de 2011 20:57
    segunda-feira, 22 de agosto de 2011 20:03
  • Opa, acho que é por aí mesmo. vou Estudar mais sobre Thread para usar na minha aplicação. vai ficar show.. Valew mesmo, O resultado eu posto aqui depois.

     

    abç

     

    segunda-feira, 22 de agosto de 2011 20:35
  • Meu código está assim.

    BackgroundWorker bkgfila = new BackgroundWorker();
              bkgfila.DoWork += new DoWorkEventHandler(bkgfila_DoWork);
    
    
    void bkgfila_DoWork(object sender, DoWorkEventArgs e)
        {
          startCronometro(idCronometro);
        }

    Alguma coisa está acontecendo que bkgfila_DoWork não está sendo chamado.

    Esse código vai fazer exetutar varias threads? Há limites para está executando o startCronometro simultâniamente através da thead?

    grato

    segunda-feira, 22 de agosto de 2011 20:56
  • Opa..bom dia...que bom q está dando certo...

    Sobre não estar sendo chamado é pq faltou esse cara...bkgFila.RunWorkerAsync(); Essa chamada é que dará o start no evento da Thread....

    Outra dica....dentro dessa chamada vc poderá passar parametros e depois pegar o valor desse parâmetro dentro do evento da Thread....seguindo o mesmo exemplo do seu código:

     

            // Essa parte será chamada quantas vezes quiser....dentro de qualquer função ou evento... 
            BackgroundWorker bkgfila = new BackgroundWorker(); 
            bkgfila.DoWork += new DoWorkEventHandler(bkgfila_DoWork); 
            bkgFila.RunWorkerAsync(idCronometro); 
            
            // Esse evento ele terá uma unica vez...pois o parametro passado será dinamico... 
            private void bkgfila_DoWork(object sender, DoWorkEventArgs e) 
            { 
                startCronometro(Convert.ToInt32(e.Argument)); 
            }
    
    Ref. ao limite de execuções...realmente não há...o limite será a máquina.....mas você poderá montar um controle ...pra limitar...sem problemas.... 
    Bom, tenho um serviço q roda em um servidor na empresa que trabalho, ele está sem limites de Threads...já acompanhei 20 Threads executando normalmente ao mesmo tempo sem problemas... :)
    Gustavo Gouveia..

     


    terça-feira, 23 de agosto de 2011 10:39
  • Olá Gustavo... bom dia!! Estou muito motivado com o código pq agora tenho uma caminho a seguir.

    Fiz exatamente como você me orientou, está funcionando! Mas alguma problema está acontecendo que quando inicia a segunda Thead a primeira para, se eu estou certo é isso que está acontecendo.

    Por exemplo se tenho dois eventos cadastrados no banco

    1ºEvento
    Início 28/08/2011
    Inicio ás 08Hr:56min

    2ºEvento
    Início 28/08/2011
    Inicio ás 08Hr:57min

    O cronometro do 1ºEvento vai começar hoje ás 8H:56min, porém quando der 08H:57min o 1ºEvento para e começa o  2ºEvento, e isso não era para acontecer.

    Segue a parte do código onde acredito que esteja o problema.

    Métodos verificaEvento()

    ...

    foreach (var item in lista)
          {
            lista = nPormocaoDao.GetAll().ToList<DM_NOVAPROMOCAO>();
    
            int minutoInicio = DateTime.Now.Minute;
            int horaimicio = DateTime.Now.Hour;
    
            if ((item.HORA_INICIO == horaimicio) && (item.HORA_INICIO_MINUTO == minutoInicio))
            {
              idCronometro = int.Parse(item.ID_TEMPOPROMO.ToString());
              BackgroundWorker bkgfila = new BackgroundWorker();
              bkgfila.DoWork += new DoWorkEventHandler(bkgfila_DoWork);
              bkgfila.RunWorkerAsync(idCronometro);
              
            }
            
          }

    void bkgfila_DoWork(object sender, DoWorkEventArgs e)
        {
          startCronometro(Convert.ToInt32(e.Argument));
        }


    e startCronometro(int id) apenas recebe o id encontrado, busca o numeros inteiros no banco e realiza o decremento.

     

    terça-feira, 23 de agosto de 2011 11:52
  • Bom dia...

     

    Hum interessante....as threads funcionam legal né...porem eu tive o mesmo problema q vc está relatando...

    solução é q seguinte...

     

    Tudo q vc for fazer dentro da Thread crie dentro dela mesmo uma instancia diferente...pq assim quando vc executa uma função q é criada como publica ...ela é interferida pela outra Thread..pq é publica...

    Explore bem Orientação a Objeto...crie seus objetos tudo dentro da Thread q deve resolver...

    vamos ao exemplo...

    Você tem a função  startCronometro certo? dentro dessa função vc deve trabalhar somente com componentes estanciados dentro da propria Thread....ou melhor tente fazer dessa função de static para não static e coloque ela em outra classe....e instanciar um novo objeto a cada chamada...

    EX:

            void bkgfila_DoWork(object sender, DoWorkEventArgs e)
            {
                classeCronometro objCronometro = new classeCronometro();
                objCronometro.startCronometro(Convert.ToInt32(e.Argument));
            }
    

     

    Acredito q dessa forma solucionará..

     

    Abraços..

     

    Gustavo Gouveia..

     

    terça-feira, 23 de agosto de 2011 12:02
  • Umm.. realmente não estou conseguindo fazer o segundo cronometro ser iniciado sem parar o primeiro.

        public void executaThead(int id)
        {
          BackgroundWorker bkgfila = new BackgroundWorker();
    
          bkgfila.DoWork += new DoWorkEventHandler(bkgfila_DoWork);
          bkgfila.RunWorkerAsync(id);
        }
    
        void bkgfila_DoWork(object sender, DoWorkEventArgs e)
        {
          startCronometro start = new startCronometro();
          start.idAtual = int.Parse(e.Argument.ToString());
          Thread thread01 = new Thread(new ThreadStart(start.starCronometro));
          thread01.Start();
        }
    
        public void verificaEvento()
        {
          foreach (var item in lista)
          {
            lista = nPormocaoDao.GetAll().ToList<DM_NOVAPROMOCAO>();
    
            int minutoInicio = DateTime.Now.Minute;
            int horaimicio = DateTime.Now.Hour;
    
             if ((item.HORA_INICIO == horaimicio) && (item.HORA_INICIO_MINUTO == minutoInicio))
            {
              idAtual = int.Parse(item.ID_TEMPOPROMO.ToString());
              executaThead(idAtual);
            }
          }
        }

    Quando há um segundo resultado no registro positico, o método executaThead(id) é chamado, que por sua vez chama o início do cronometro substituido o primiro cronometro que estava sendo executado. Precisava que o startCronometro não fosse substituido, mas que continuasse sendo executado em uma outra thread, ou de alguma outra maneira.

    [=-( }

    terça-feira, 23 de agosto de 2011 19:42
  • Poxa vida....que coisa....

     

    O meu problema estava na conexão com o banco...e depois de muito trabalho consegui fazendo dessa forma...no meu caso uma conexão interferia em outra.....fazendo com que um processo esperasse o outro....etc...

    Vou ver se consigo ter mais alguma ideia.... :(

     

    Abraços..

     

    Gustavo Gouveia...

     

    terça-feira, 23 de agosto de 2011 22:28
  • O que pensei é criar uma lista de Thread e toda vez que o método validarThread encontrar uma condição verdadeira ele cria uma nova instancia da thread e add ela na lista. Dentro dessa thread estou chamando o método cronometrar que apenas busca o valor do banco seta algumas veiáveis e chama o cronometro propriamente dito.

    Porque o cronometro para? Tenho um Time que fica chamando o verificaEvento(). Esse método testa uma condição, no caso de verdadeira chama o método cronometrar() que busca os dados de uma linha da tabela e chama e inicia o cronometro. Como o Time não para, fica chamando o verificaEvento(), se um segundo registro da tabela for encontrado ele repete todo o processo, substituindo o primeiro resultado encontrado, parando o primeiro cronometro e começando a executar o segundo.

    Gostaria que tivesse alguma maneira de quando verificaEvento() encontrar uma ocorrência verdadeira ele alocasse em uma parte da memória o cronometrar(). Aí quando o verificaEvento() encontrasse um segundo registro da tabela o obedecesse a condição estabelecida não substituiria o valor da primeira condição verdadeira.

    Fiz os testes com esse código mas mesmo assim o cronomtrar() está sendo substituido.

      if ((item.HORA_INICIO == horaimicio) && (item.HORA_INICIO_MINUTO == minutoInicio))
      {
     
       start.idAtual = idAtual;
       thread01 = new Thread(new ThreadStart(start.cronometrar));
       thread01.IsBackground = true;
       thread01.Start();
       listaThread.Add(thread01);
       
      }

     







    quarta-feira, 24 de agosto de 2011 11:38