System.Timer -- blockiert Anwendung

freakbrother

Mitglied
Hallo!

Ich hab ein Problem mit dem System.Timer in meiner Applikation.

Jedesmal wenn der Timer die Ausführung startet, blockiert meine gesamte Applikation.

Nun ja, dann hab ich mir gedacht ich spendier diesen System.Timer (der ja
eigentlich schon ein eigener Thread ist und vom Prinzip her nichts anderes ist als
ein System.Threading.Timer) zusätzlich einen eigenen Thread.

Aber auch das hat nichts geholfen.
Hat hier irgendjemand eine Ahnung, ob das mit einer Prozess - Priorität der Timers
allgemein zu tun hat und wie man dies unterbinden könnte, sodass der Timer sowie dessen Ausführung im Hintergrund arbeitet und man in der Applikation
*normal* weiterarbeiten kann?

Wäre echt fein wenn mir jemand weiterhelfen könnte.
Beste Grüße!

Hier das kleine Codeschnippsel:

Code:
using System;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SystemTimer
{
    public partial class Form1 : Form
    {
        public const string constr = @"Database=;Server=localhost;user id=;password=";
        System.Timers.Timer tmrs = new System.Timers.Timer();
        private AutoResetEvent autoEvent;
        private DataSet dts = new DataSet();
        delegate void delTmrTest();

        public Form1()
        {
            InitializeComponent();

            List<int> list = new List<int>(12);

            for (int i = 15; i <= 180; i += 15)
                list.Add(i);

            comboBox1.DataSource = list;
            tmrs.Elapsed += new System.Timers.ElapsedEventHandler(tmrs_Elapsed);
        }

        private void fillDataGrid()
        {
            dataGridView1.DataSource = dts.Tables[0];
        }

        void tmr(object interval)
        {
            autoEvent = new AutoResetEvent(false);
            tmrs.Interval = Convert.ToInt32(interval);
            tmrs.AutoReset = true;
            tmrs.Start();
        }

        void tmrs_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            BeginInvoke(new delTmrTest(showGridWithData));
        }

        private void showGridWithData()
        {
            string sqlSelect = "SELECT * FROM TestTable";
            SqlDataAdapter adr = new SqlDataAdapter(sqlSelect, constr);
            adr.Fill(dts);
            dataGridView1.DataSource = dts.Tables[0];
            textBox1.Text += "Timer Event " + Environment.NewLine + DateTime.Now.ToString("hh:mm:ss.fff");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread t1 = new Thread(new ParameterizedThreadStart(tmr));
            int interval = Convert.ToInt32(comboBox1.SelectedItem) * 1000;
            t1.Start(interval);
        }

        private void comboBox1_SelectedIndexChanged(object s, EventArgs e)
        {
            if (comboBox1.SelectedItem != null && tmrs != null)
            {
                tmrs.Stop();
                tmrs.Interval = Convert.ToInt32(comboBox1.SelectedItem) * 1000;
                tmrs.Start();
            }

        }
    }
}
 

Alexander Schuc

crazy-weasel
Hi.

Ich hab das ganze mal ausprobiert, allerdings anstatt der Datenbank abfrage hab ich mir das DataSet sozusagen von Hand befüllt.
Dabei gabs keine Probleme, die Anwendung hat durch und durch reagiert.

Das Problem wird also die Abfrage sein. Der ganze Code mit dem Timer läuft ja in nem anderne Thread, der kann also gar nicht blockieren.

Also probiers vielleicht mal so rum:

C#:
void tmrs_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
	//BeginInvoke(new delTmrTest(showGridWithData));
	showGridWithData();
}

private void showGridWithData()
{
	string sqlSelect = "SELECT * FROM TestTable";
	SqlDataAdapter adr = new SqlDataAdapter(sqlSelect, constr);
	adr.Fill(dts);


	Invoke((MethodInvoker)delegate()
	{
		dataGridView1.DataSource = dts.Tables[0];
		textBox1.Text += "Timer Event " + Environment.NewLine + DateTime.Now.ToString("hh:mm:ss.fff");
	});
}

lg,.. :)
 

freakbrother

Mitglied
Servus Alex ;-)

Natürlich ist das *Problem* die Abfrage, weil Sie eben etwas länger dauert.
Und genau da liegt der Drache im Moorbad verscharrt:
Sobald die Abfrage gestartet wird und die Daten geladen werden, blockiert die Applikation.
Sollte doch nicht sein wenn es in einem eigenen Thread läuft.
Ist ja auch *nur* eine Ausführung
Oder habe ich da ein wesentliches Verständnisproblem?

Ich muss auch anmerken das ich das mit dem DataSet in diesen Testprojekt mache.
Im eigentlichen Projekt werden die Daten mittels DataReader und einer eigenen Tables - Klasse geladen und dem grid zugewiesen.

Aber trotzdem sehr elegant mit der anonymen methode beim Delegate ;-)
wenns im endeffekt auch leider den gleichen effekt hat :-(
 

freakbrother

Mitglied
So jetzt hab ich das ganze nochmal ausgetestet und bin zu folgendem Ergebnis gekommen.
Es ist tatsächlich so, dass bei Invoke, also der Threadrückführung, das Blockieren der Anwendung passiert und nicht bei der Abfrage der Daten :) .
In meinem Fall also bei der Zuweisung der Daten zum DataGrid.
Auf ein minimum reduzieren konnte ich das Blockieren der Anwendung, indem ich die Invoke - Eigenschaft des Controls verwende und innerhalb dessen die Zuweisung durchführe.

Danke nochmal an Alex für die Hilfe beim Verstehen der Problematik!!
 

Neue Beiträge