• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

crisoft

[RESOLVIDO] Sugestão para actualizar um painel de minuto a minuto

8 mensagens neste tópico

Boa tarde.

Estou a desenvolver uma aplicação que consiste num painel, onde são visualizadas alguns estados de determinadas tabelas de uma BD em SQL.

O problema que estou a ter é de que necessito que este painel seja actualizado de minuto a minuto sem necessitar de qualquer intervenção de um utilizador.

Já tentei criar um Timer para este efeito mas depois não consigo dentro do TimeEvent invocar qualquer objecto não estático, ou seja, não consigo invocar objectos do ecran.

Alguém me sabe dar uma sugestão para eu resolver isto?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Como é que estás a carregar a informação no Painel??

O mais certo (na minha opinião) será teres uma função que vai-te carregar a informação dentro do painel, e depois no Timer chamas essa mesma função!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Como é que estás a carregar a informação no Painel??

O mais certo (na minha opinião) será teres uma função que vai-te carregar a informação dentro do painel, e depois no Timer chamas essa mesma função!

Foi a solução inicial que eu tinha pensado.

Mas ao tentar chamr a função dentro do Timer obtenho o erro de que não posso invocar objectos pertencentes a Threads não estáticas como a UI.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Podes mostrar o código para que se perceba melhor como tas a tentar fazer ?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Podes mostrar o código para que se perceba melhor como tas a tentar fazer ?

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Navigation;

using System.Windows.Shapes;

using System.Collections.ObjectModel;

using System.Threading;

using System.Timers;

namespace Painel

{

    /// <summary>

    /// Interaction logic for Main.xaml

    /// </summary>

    public partial class Main : Window

    {

        System.Timers.Timer aTimer = new System.Timers.Timer(10000);

        public Main()

        {

            InitializeComponent();

            aTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimedEvent);

            aTimer.Interval = 5000;

            aTimer.Enabled = true;

            aTimer.Start();

        }

        private void btnFechar_Click(object sender, RoutedEventArgs e)

        {

            this.Close();

            Application.Current.Shutdown();

        }

        private void btnActualizar_Click(object sender, RoutedEventArgs e)

        {

            Actualizar();

        }

        private void Actualizar()

        {

                tbPainel1.ItemsSource = new Lojas1();

                tbPainel2.ItemsSource = new Lojas2();

                tbPainel3.ItemsSource = new Lojas3();

        }

        private static void OnTimedEvent(object source, System.Timers.ElapsedEventArgs e)

        {

          //    MessageBox.Show("The Elapsed event was raised at {0}" + e.SignalTime);

         

            Painel.Actualizar();

        }

     

    }

}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Como este código não funciona porque não posso chamar objectos não estáticos a partir de um timer estou a tentar resolver da seguinte forma.

Desisto do timer e coloco a actualização dentro de um ciclo do estilo:

private void Actualizar()

        {

            while (true)

            {

                tbPainel1.ItemsSource = new Lojas1();

                tbPainel2.ItemsSource = new Lojas2();

                tbPainel3.ItemsSource = new Lojas3();

                Thread.Sleep(30000);

            }

        } 

Só que isto pendura-me a aplicação...

O que eu pretendia era p.ex. que o cliclo fosse interrompido se presssionasse a tecla ESC e até podia fechar a aplicação caso fosse interrompido.

Como posso ler uma tecla e determinar se ela é a tecla ESC?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Boas,

Com esse código vai bloquear a thread da UI da tua aplicação. Muito feio  ;)

Em windows forms os elementos da janela apenas podem ser alterados pela thread que os inicia, ou seja, pela thread da UI. É por essa razão que não ter permite alterar no método registado no evento de TimeEvent. Foi a forma encontrada para garantir que não que esses elementos são Thread-safe.

Para resolveres isso há uma forma simples. Todos os tipos derivados System.Windows.Forms.Control tem um método que permite pedir à thread que criou o controlo para executar um delegate, é o método BeginInvoke. Repara neste exemplo:

public delegate void MyDelegate(Label myControl, string myArg2);

private void Button_Click(object sender, EventArgs e)
{
   object[] myArray = new object[2];

   myArray[0] = new Label();
   myArray[1] = "Enter a Value";
   myTextBox.BeginInvoke(new MyDelegate(DelegateMethod), myArray);
}

public void DelegateMethod(Label myControl, string myCaption)
{
   myControl.Location = new Point(16,16);
   myControl.Size = new Size(80, 25);
   myControl.Text = myCaption;
   this.Controls.Add(myControl);
}

Mais informações aqui: http://msdn.microsoft.com/en-us/library/a06c0dc2.aspx

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Pois, efectivamente eu já tinha chegado a essa conclusão, de que ia pendurar a thread da UI, mas como estava sem alternativas, tentei procurar a solução por aí...

Entretanto a solução que deste era a única hipótese viável, por invocação assíncrona.

Mas ia ter imenso trabalho, para colocar num delegate toda a programação dos meus controles, já que pela sua complexidade, eu tinha essa programação em XAML, visto a  minha aplicação ser uma WPF Apllication.

Contudo, depois de fazer a leitura de uma série de artigos que encontrei na NET, descobri a solução mais simples de todas...

Basta substituir o Timer derivado da System.Timers pelo System.Windows.Forms.Timer, e o método Elapsed, pelo método Tick, só existente no Timer da System.Windows.Forms... et voilá... já funciona...

Os Windows Timers são Single-Threaded logo a invocação de outras threads só pode ser feita assíncronamente, contudo o Windows.Forms.Timer foi desenhado com o objectivo de poder processar objectos da Thread UI...

Não sei se esta afirmação está correcta mas foi isso que deduzi...

O meu código ficou só assim, tão simples como isto:

    public partial class Main : Window

    {

        System.Windows.Forms.Timer aTimer = new System.Windows.Forms.Timer();

        public Main()

        {

            InitializeComponent();

            aTimer.Tick += new System.EventHandler(aTimer_Tick);

            aTimer.Interval = 5000;

            aTimer.Enabled = true;

            aTimer.Start();

        }

        private void aTimer_Tick(object sender, EventArgs e)

        {

            tbPainel1.ItemsSource = new Lojas1();

            tbPainel2.ItemsSource = new Lojas2();

            tbPainel3.ItemsSource = new Lojas3();

        }

0

Partilhar esta mensagem


Link 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