Laden...

WinForm lässt sich nicht mehr bewegen etc nachdem code aktiv ist

Erstellt von Reaper_97 vor 4 Jahren Letzter Beitrag vor 4 Jahren 2.619 Views
R
Reaper_97 Themenstarter:in
13 Beiträge seit 2019
vor 4 Jahren
WinForm lässt sich nicht mehr bewegen etc nachdem code aktiv ist

Ich will einen eigenen Hardware Monitor für meine PC's erstellen und bin auf einen Thread vom Open Hardware Monitor gestoßen. Alles klappt super falls man nur eine Ausgabe über die Konsole haben will, aber sobald ein Element zb Label oder Progressbar angesteuert werden soll geht auf der Form gar nichts mehr... kein bewegen , schließen usw.

using OpenHardwareMonitor.Hardware;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HwMonitor
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void Form2_Load(object sender, EventArgs e)
        {
           
        }
        public class UpdateVisitor : IVisitor
        {
            public void VisitComputer(IComputer computer)
            {
                computer.Traverse(this);
            }
            public void VisitHardware(IHardware hardware)
            {
                hardware.Update();
                foreach (IHardware subHardware in hardware.SubHardware) subHardware.Accept(this);
            }
            public void VisitSensor(ISensor sensor) { }
            public void VisitParameter(IParameter parameter) { }
        }
        public void GetSystemInfo()
        {
            var updateVisitor = new UpdateVisitor();
            var computer = new Computer();
            computer.Open();
            computer.CPUEnabled = true;
            computer.Accept(updateVisitor);
            for (int i = 0; i < computer.Hardware.Length; i++)
            {
                if (computer.Hardware[i].HardwareType == HardwareType.CPU)
                {
                    for (int j = 0; j < computer.Hardware[i].Sensors.Length; j++)
                    {
                        if (computer.Hardware[i].Sensors[j].SensorType == SensorType.Temperature)
                        {
                           SetProgressBar(computer.Hardware[i].Sensors[j].Name, (float)computer.Hardware[i].Sensors[j].Value);
                            //Console.WriteLine($"{computer.Hardware[i].Sensors[j].Name}: {computer.Hardware[i].Sensors[j].Value}\u00B0C\r");
                        }
                    }
                }
            }
            computer.Close();           
        }

        public void SetProgressBar(string name, float value)
        {
            switch(name)
            {
                case "CPU Core #1":                  
                    progressBar1.Value = (int)value;
                    Thread.Sleep(100);
                    label1.Text = $"{Math.Round(value, 1)}%";
                    Thread.Sleep(100);
                    break;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            while (true)
            {
                GetSystemInfo();
                Thread.Sleep(1000);
            }
        }
    }
}
J
251 Beiträge seit 2012
vor 4 Jahren

Hallo,

bist Du Dir sicher, dass Du im Click-Event vom Button eine Endlosschleife haben möchtest?

Edit:
Wenn man Dein Thread.Sleep() mit der Schleife gegen z.B. einen Timer mit einen Intervall von 1000 tauscht, sähe es (vom Code her alleine schon) um einiges besser aus.

R
Reaper_97 Themenstarter:in
13 Beiträge seit 2019
vor 4 Jahren

Ja ich hatte es mit einem Timer vorher aber, ich habe es gewechselt weil nicht einmal die Form sich geöffnet hatte.

Trotz des Timers kann reagiert meine WinForm ca nur alle paar sekunden auf einen befehl wie schließen oder bewegen etc.. Kann man dass irgendwie verbessern weil so ist es nicht wirklich nutzbar

Hinweis von Abt vor 4 Jahren

Keine Full Quotes
[Hinweis] Wie poste ich richtig?

R
Reaper_97 Themenstarter:in
13 Beiträge seit 2019
vor 4 Jahren

Ja dass ist mir nicht neu aber habe nie damit gearbeitet.

Kannst du mir bitte helfen damit dass es funktioniert bin neu auf dem Gebiet?

Hinweis von Abt vor 4 Jahren

Keine Full Quotes
[Hinweis] Wie poste ich richtig?

1.696 Beiträge seit 2006
vor 4 Jahren

Kannst du mir bitte helfen damit dass es funktioniert bin neu auf dem Gebiet?

z.B. starte deine Methode in einem Thread und aktualisiere dein Progressbar über delegate.

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

R
Reaper_97 Themenstarter:in
13 Beiträge seit 2019
vor 4 Jahren

Ja danke dafür aber wie soll ich dass hier machen:?

Hinweis von Abt vor 4 Jahren

Keine Full Quotes
[Hinweis] Wie poste ich richtig?

1.696 Beiträge seit 2006
vor 4 Jahren

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

R
Reaper_97 Themenstarter:in
13 Beiträge seit 2019
vor 4 Jahren

Danke aber dass habe ich mir auch schon angeschaut aber egal was ich versuche es laggt immer noch rum ... Kannst du mir zeigen wie ich es richtig implementiere in meinen Code? Würde mir viel mehr helfen als der Beitrag.

Hinweis von Abt vor 4 Jahren

Keine Full Quotes
[Hinweis] Wie poste ich richtig?

R
Reaper_97 Themenstarter:in
13 Beiträge seit 2019
vor 4 Jahren

Dass wäre einfach mit dem Timer (1000ms).

Ich habe die versuche mit task etc rausgemacht weil es nicht funktioniert hatte.

using OpenHardwareMonitor.Hardware;
using System;
using System.Windows.Forms;

namespace HwMonitor
{
    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
        }

        private void Form3_Load(object sender, EventArgs e)
        {
        }

        public class UpdateVisitor : IVisitor
        {
            public void VisitComputer(IComputer computer)
            {
                computer.Traverse(this);
            }
            public void VisitHardware(IHardware hardware)
            {
                hardware.Update();
                foreach (IHardware subHardware in hardware.SubHardware) subHardware.Accept(this);
            }
            public void VisitSensor(ISensor sensor) { }
            public void VisitParameter(IParameter parameter) { }
        }
        public void GetSystemInfo()
        {
            var updateVisitor = new UpdateVisitor();
            var computer = new Computer();
            computer.Open();
            computer.CPUEnabled = true;
            computer.Accept(updateVisitor);
            for (int i = 0; i < computer.Hardware.Length; i++)
            {
                if (computer.Hardware[i].HardwareType == HardwareType.CPU)
                {
                    for (int j = 0; j < computer.Hardware[i].Sensors.Length; j++)
                    {
                        if (computer.Hardware[i].Sensors[j].SensorType == SensorType.Temperature)
                        {
                            SetProgressBar(computer.Hardware[i].Sensors[j].Name, (float)computer.Hardware[i].Sensors[j].Value);
                        }
                    }
                }
            }
            computer.Close();
        }

        public void SetProgressBar(string name, float value)
        {
            switch (name)
            {
                case "CPU Core #1":
                    progressBar1.Value = (int)value;
                    label1.Text = $"{Math.Round(value, 1)}%";
                    break;
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            GetSystemInfo();
        }
    }
}
R
Reaper_97 Themenstarter:in
13 Beiträge seit 2019
vor 4 Jahren

So sieht es zwar gut aus aber wenn ich zb alle 4 Kerne abfrage und nicht nur 1 kann man die form nur alle paar sekunden ziehen /minimieren und maximieren etc und kein Button reagiert mehr.

16.806 Beiträge seit 2008
vor 4 Jahren

Musst das Abfragen eben in einen Task auslagern.
Im Endeffekt ist es das: [FAQ] Warum blockiert mein GUI?

R
Reaper_97 Themenstarter:in
13 Beiträge seit 2019
vor 4 Jahren

Musst das Abfragen eben in einen Task auslagern.
Im Endeffekt ist es das:
>

Ändert sich nichts ist immer noch nicht nutzbar die Form. Progressbar / Label ändert sich richtig aber nur lade Zeichen über der Form und keine Reaktion auf befehle (zb Button).

using OpenHardwareMonitor.Hardware;
using System;
using System.Threading;
using System.Windows.Forms;

namespace HwMonitor
{
    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
        }
        Thread systemInfo;
        private void Form3_Load(object sender, EventArgs e)
        {
            systemInfo = new Thread(new ThreadStart(GetSystemInfo));
            systemInfo.Start();
        }

        public class UpdateVisitor : IVisitor
        {
            public void VisitComputer(IComputer computer)
            {
                computer.Traverse(this);
            }
            public void VisitHardware(IHardware hardware)
            {
                hardware.Update();
                foreach (IHardware subHardware in hardware.SubHardware) subHardware.Accept(this);
            }
            public void VisitSensor(ISensor sensor) { }
            public void VisitParameter(IParameter parameter) { }
        }
        public void GetSystemInfo()
        {
            try
            {
                while (true)
                {
                    var updateVisitor = new UpdateVisitor();
                    var computer = new Computer();
                    computer.Open();
                    computer.CPUEnabled = true;
                    computer.Accept(updateVisitor);
                    for (int i = 0; i < computer.Hardware.Length; i++)
                    {
                        if (computer.Hardware[i].HardwareType == HardwareType.CPU)
                        {
                            for (int j = 0; j < computer.Hardware[i].Sensors.Length; j++)
                            {
                                if (computer.Hardware[i].Sensors[j].SensorType == SensorType.Temperature)
                                {

                                    if (progressBar1.InvokeRequired)
                                    {
                                        progressBar1.Invoke(new Action(GetSystemInfo));
                                    }
                                    else
                                    {
                                        SetProgressBar(computer.Hardware[i].Sensors[j].Name, (float)computer.Hardware[i].Sensors[j].Value);
                                    }
                                }
                            }
                        }
                    }
                    computer.Close();
                    Thread.Sleep(100);
                }                
            }
            catch(ThreadAbortException ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        public void SetProgressBar(string name, float value)
        {
            switch (name)
            {
                case "CPU Core #1":
                    progressBar1.Value = (int)value;
                    label1.Text = $"{Math.Round(value, 1)}%";
                    break;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            systemInfo.Abort();
            Console.WriteLine("Thread has been stopped!");
        }
    }
}
16.806 Beiträge seit 2008
vor 4 Jahren

Etwas unsauberer Code; aber aus dem Thread heraus dürfte die UI nicht mehr blockieren oder Anzeichen davon haben.
Die Endlosschleife ist natürlich total unnötig und sollte periodisch erfolgen.
[Tutorial] Vertrackte Fehler durch Vergleich von echtem Projekt mit minimalem Testprojekt finden

R
Reaper_97 Themenstarter:in
13 Beiträge seit 2019
vor 4 Jahren

Etwas unsauberer Code; aber aus dem Thread heraus dürfte die UI nicht mehr blockieren oder Anzeichen davon haben.
Die Endlosschleife ist natürlich total unnötig und sollte periodisch erfolgen.

Warum ist die Endlosschleife total unnötig? Ich will ja die Aktuellen werte haben jede x sekunden oder ms?

Der Thread klappt aber nur ohne schleife.

4.931 Beiträge seit 2008
vor 4 Jahren

Was soll denn der rekursive Aufruf

 progressBar1.Invoke(new Action(GetSystemInfo));

?
Du mußt (nur) SetProgressBar per Invoke aufrufen (evtl. in eine eigene Methode auslagern).

PS: Mußt du denn UpdateVisitor sowie Computer jedesmal wieder in der Schleife neu erzeugen? Besser wäre doch, diese nur einmalig zu erzeugen und dann nur noch deren Methoden periodisch aufzurufen.

16.806 Beiträge seit 2008
vor 4 Jahren

Reaper_97, bitte unterlass endlich die Full Quotes.
[Hinweis] Wie poste ich richtig?

Keine Lust quasi jeden Post von Dir editieren zu müssen.
Danke. 👍

R
Reaper_97 Themenstarter:in
13 Beiträge seit 2019
vor 4 Jahren

Es waren nicht immer full quotes aber wenn du meinst.

Da leider keine passende Antwort bisher gekommen ist hatte ich mich den ganzen mittag schlau gemacht und eine passende Lösung gefunden mit weniger Code.

16.806 Beiträge seit 2008
vor 4 Jahren

Ich hoffe Du verstehst wenigstens den Code, den Du von irgendwo kopierst.
Den Code hier hast offenbar selbst nicht verstanden =)

Die Rekursion, die Th69 nannte, gehört da natürlich nicht hin.
Wäre aber durch ein selbstständiges Debuggen ( [Artikel] Debugger: Wie verwende ich den von Visual Studio? ) aufgefallen.

Der Thread klappt aber nur ohne schleife.

Ist natürlich totaler Humbug. Man kann problemlos eine Method periodisch starten, die dann einen Task (oder wenn wirklich notwendig einen Thread) ausführt.
Mit Reactive Extensions ist das in zwei Zeilen gemacht.

Aber ja, den Code hier kann man extrem schlanker gestalten - das ist korrekt.

R
Reaper_97 Themenstarter:in
13 Beiträge seit 2019
vor 4 Jahren

Ich verstehe alles, nur dass problem waren die threads. Mit denen habe ich bisher noch nicht viel gearbeitet weil es nicht nötig war bei den meisten Sachen. Und davon abgesehen ich habe nicht irgendein Code kopiert oder sonst was. Ich habe nur online eine funktion wieder gesehen die ich vergessen hatte und dass Problem behoben hat was dein Kommentar nicht konnte wie man sieht.

Und wegen dem x gehört nicht hin stimmte auch nicht ganz weil ich einfach dass alte kopiert hatte wo es noch nicht richtig abgeändert war lol. Davon abgesehen mache ich dass alles als Hobby und Arbeite damit nicht.

Hinweis von Abt vor 4 Jahren

Und wieder ein Full Quote!
[Hinweis] Wie poste ich richtig?

16.806 Beiträge seit 2008
vor 4 Jahren

Bin mir gerade nicht sicher, ob der Edit Deine Absicht war, dass Du dort quasi den halben Thread nachträglich als Fullquote eingefügt hast, nachdem ich Deinen erneuten Fullquote entfernt habe....

Ich war aber neugierig, was das NuGet Paket OpenHardwareMonitor so bietet.
Daher habe ich Deinen Code kurz als Basis genommen und mit den Tipps hier im Thread korrigiert bzw erweitert.

Deine Symptome kann ich nachvollziehen aber mit den Tipps hier im Thread lösen:
computer.Accept blockiert die UI, sodass diese sich nicht ordentlich verschieben lässt. Standardproblem von [FAQ] Warum blockiert mein GUI?

Gesamthema gelöst anhand der Tipps hier im Forum bzw. in den Antworten. 👍
Es ist das eine, wenn man es nicht hinbekommen, weil man noch recht neu ist - aber dann muss man sagen, wo genau es hängt.
Die Aussage

Da leider keine passende Antwort bisher gekommen ist

ist jedoch einfach eine Ohrfeige für die Leute, die hier versucht haben Dir zu helfen.

using System;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenHardwareMonitor.Hardware;

namespace WindowsFormsApp1
{
    public class UpdateVisitor : IVisitor
    {
        public void VisitComputer(IComputer computer)
        {
            computer.Traverse(this);
        }

        public void VisitHardware(IHardware hardware)
        {
            hardware.Update();
            foreach (IHardware subHardware in hardware.SubHardware) subHardware.Accept(this);
        }

        public void VisitSensor(ISensor sensor)
        {
        }

        public void VisitParameter(IParameter parameter)
        {
        }
    }

    public static class ControlExtensions
    {
        public static void UIThread(this Control source, Action body)
        {
            if (source.InvokeRequired)
            {
                source.BeginInvoke(body);
            }
            else
            {
                body.Invoke();
            }
        }
    }

    public partial class Form1 : Form
    {
        private IDisposable _subscription;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (_subscription is null)
            {
                _subscription = Observable.Interval(TimeSpan.FromSeconds(1))
                    .Subscribe(async x => await ReadSystemInfoAsync());
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            _subscription?.Dispose();
            _subscription = null;

        }

        public async Task ReadSystemInfoAsync()
        {
            await Task.Run(() =>
            {


                var updateVisitor = new UpdateVisitor();
                var computer = new Computer();

                try
                {
                    computer.Open();
                    computer.CPUEnabled = true;

                    computer.Accept(updateVisitor);

                    foreach (IHardware t in computer.Hardware)
                    {
                        if (t.HardwareType != HardwareType.CPU) continue;

                        foreach (ISensor t1 in t.Sensors)
                        {
                            if (t1.SensorType != SensorType.Load) continue;

                            SetProgressBar(t1.Name, t1.Value);
                        }
                    }
                }
                catch (Exception e)
                {
                    // Mach irgendwas mit Exceptions
                }
                finally
                {

                    computer.Close();
                }
            });
        }


        public void SetProgressBar(string name, float? load)
        {
            float value = load.GetValueOrDefault(0);

            switch (name)
            {
                case "CPU Core #1":
                    this.UIThread(() =>
                    {
                        progressBar1.Value = (int)value;
                        label1.Text = $"{Math.Round(value, 1)}%";
                    });

                    break;
            }
        }
    }
}

PS: OpenHardwareMonitor mag offenbar meine CPU nicht; daher statt der Temperatur die Auslastung als Sensor genommen.

463 Beiträge seit 2009
vor 4 Jahren

Nur mein Eindruck beim Lesen des Themas hier:

Es macht keinen Sinn Code nur zu kopieren ohne ihn zu verstehen und noch schlimmer - zu glauben/behaupten ihn zu verstehen, aber durch seine Antworten zeigen, dass man davon noch meilenweit entfernt ist.

Ansonsten wurde zum Thema/Problem selber ja schon alles gesagt ([FAQ] Warum blockiert mein GUI?)

4.931 Beiträge seit 2008
vor 4 Jahren

Ich habe gerade in Sicherheitslücke in vorinstallierter Analyse-Software macht HP-Rechner unsicher gelesen, daß es wohl einen Safety-Bug im "Open Hardware Monitor" gibt.
Leider ist das Projekt Open Hardware Monitor wohl seit fast 3 Jahren nicht mehr gepflegt - du solltest also vorsichtig sein.