Laden...

Performance-Problem in MouseMove Event vermeiden

Erstellt von planetberlin vor 10 Jahren Letzter Beitrag vor 10 Jahren 2.218 Views
planetberlin Themenstarter:in
23 Beiträge seit 2010
vor 10 Jahren
Performance-Problem in MouseMove Event vermeiden

Guten Tag,
Und wieder brauche ich Unterstützung. Wäre nett, wenn mir jemand eine Idee geben könnte zu dem folgenden Fall.

Ich habe in meiner Form 2 Panels.

Panel1: LineChartControl
Panel2: Datagridview

(siehe Screenshot)

Beim MouseMove über das Chart (links) sollen abhängig von der X Position der Maus, die Y Werte in der "Value" Spalte des DGV angezeigt werden.

Das funktioniert momentan, aber die Performance lässt sehr zu wünschen übrig.

Hauptgrund ist wohl dieser:


private void chart1_MouseMove(object sender, MouseEventArgs e)
        {
            // Abonnement vom MouseMove des ChartControls
            this.chart1.MyMouseMove();

            // Prüfen, welche Rows gecheckt sind
            // wenn checked, dann aktueller Wert in entsprechende DGV Zelle
            foreach (DataGridViewRow dr in dgv_channels.Rows)
            {
                if ((bool)dr.Cells[0].Value == true)
                {
                    selectedcontainer.FileObject.GetValuesByTime(xtime, Convert.ToInt32(dr.Cells[1].Value) - 1);
                    dgv_channels.Rows[dr.Index].Cells[4].Value = selectedcontainer.FileObject.mes.Current_Value.ToString("N2");
                }

            }
        }

In dem MouseMove eine foreach Schleife zu verwenden, finde ich nicht elegant und suche einen anderen Weg, dieses Problem zu lösen.

Wäre nett, wenn jemand helfen könnte.
Danke vorab
pb

Anhang:

S
417 Beiträge seit 2008
vor 10 Jahren

Hallo,

dein Code macht doch momentan immer das gleich, also unabhängig von der Mouse position. Hast du da nicht eine Prüfung vergessen?

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo planetberlin,

// Abonnement vom MouseMove des ChartControls  
this.chart1.MyMouseMove();  

wenn der Kommentar stimmt bzw. ich ihn richtig verstehe, abonnierst du darin das MouseMove des ChartControls. Das wäre natürlich fatal. Den EventHandler sollte man nur einmal, z.B. im Konstruktor abonnieren.

Ansonsten geht es mir wie Sarc: ich sehe nicht, wo da etwas in Abhängigkeit von der MousePosition passiert.

herbivore

M
198 Beiträge seit 2010
vor 10 Jahren

Hallo!

vielleicht kann man eine Linq Abfrage machen???

planetberlin Themenstarter:in
23 Beiträge seit 2010
vor 10 Jahren

Den EventHandler sollte man nur einmal, z.B. im Konstruktor abonnieren

Herbivore, Danke dafür, das werde ich heute nacht noch mal beherzigen und verbessern.

..., ich sehe nicht, wo da etwas in Abhängigkeit von der MousePosition passiert

Bitte schau nochmal auf den neuen Screenshot.
Pkt1: Kanal is gecheckt und wird in Chart überladen.
Pkt2: Das abonnierte Mousemove des ChartControls liefert mir die X-Position zurück. Via Methodenzugriff auf einen "DatenContainer" erhalte ich zum X Value, den aktuellen Y-Value zurück, den ich an das DGV überlade.
Pkt3: Aktueller Wert wird in DGV angezeigt (abhängig von Mouseposition)

Das Problem jedoch:
Die foreach-Schleife. Die fragt bei jeder Bewegung der Maus alle gelisteten Kanäle ab, ob sie gecheckt sind oder nicht. Bei "checked true" wird der Y Value im DGV angezeigt.

Die foreach-Schleife macht aber alles sehr langsam.

Danke für Eure Hilfe.
Gruß
pb

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo planetberlin,

Die foreach-Schleife macht aber alles sehr langsam.

... oder eben das x-fache Abonnieren des EventHandlers. Diese Möglichkeit solltest du erstmal ausschließen.

herbivore

D
24 Beiträge seit 2009
vor 10 Jahren

Du könntest dir ja den Rowindex merken, wenn eine Checkbox aktiviert wird. Dann brauchst du nur diese Rows ansprechen und musst nicht alle durchgehen.

Aber der Hinweis von Herbivore hat natürlich Prio 😃

planetberlin Themenstarter:in
23 Beiträge seit 2010
vor 10 Jahren

Hallo,

Den EventHandler sollte man nur einmal, z.B. im Konstruktor abonnieren.

So habe ich es gemacht. Beim MouseMove im panel1 (chart1_MouseMove) wird mir die MouseTime via Eventdelegate "weitergereicht". Scheint für mich i.O. - ist es aber wohl nicht, denn:

Ich habe mal zum Test die angesprochene foreach-Schleife /* ... */ auskommentiert und in der Tat, das Performance Problem stammt aus dem Eventdelegieren.

Liegt es evtl. daran, dass die Mouseposition eigentlich aus der "ChartStyle" Klasse des ChartControls stammt?
Muss in einem solchen Fall 2x "delegiert werden (ChartStyle > ChartControl > MainFrom) ?
Oder, Von ChartStyle direkt an MainForm?

Danke für die Hilfe.
pb

PS.:
Danke für die Ideen zur foreach-Schleife. Dazu schreibe ich nochmal später.

Das Abonnement sieht so aus.

In der MainForm:


private double xtime = 0;

public MainForm()
        {
            InitializeComponent();
            ...
            ...
            
            // Hier das einmalige Abo.
            this.chart1.MyEvent += new ChartControl.Chart.EventDelegate(MouseMoveEventHandler);
        }

private void MouseMoveEventHandler(double _x)
        {
            // Die X Mouse Time wird im Label angezeigt
            lbl_x.Text = DateTime.FromOADate(_x).ToString("HH:mm:ss.fff");
            xtime = _x;
        }

private void chart1_MouseMove(object sender, MouseEventArgs e)
        {
            
            this.chart1.MyMouseMove();

            // Die angesprochene foreach-Schleife
            foreach (DataGridViewRow dr in dgv_channels.Rows)
            {
                if ((bool)dr.Cells[0].Value == true)
                {
                    selectedcontainer.FileObject.GetValuesByTime(xtime, Convert.ToInt32(dr.Cells[1].Value) - 1);

                    dgv_channels.Rows[dr.Index].Cells[4].Value = selectedcontainer.FileObject.mes.Current_Value.ToString("N2");
                }

            }

        }

im ChartControl:


private ChartStyle cs;
...
...

public delegate void EventDelegate(double sender_x);
public event EventDelegate MyEvent;

public Chart()
        {
            InitializeComponent();

            cs = new ChartStyle(this);
            ...
        }

private void OnEvent(double x)
        {
            if (MyEvent != null)
            {
                MyEvent(x);
            }
        }

// Eigenes Mouse-Event
public void MyMouseMove()
        {
            double _mt = cs.MouseTime();

            // Daten weiterreichen
            OnEvent(_mt);
            
        }