Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
WinForm lässt sich nicht mehr bewegen etc nachdem code aktiv ist
Reaper_97
myCSharp.de - Member



Dabei seit:
Beiträge: 13

Themenstarter:

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

beantworten | zitieren | melden

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);
            }
        }
    }
}
Attachments
private Nachricht | Beiträge des Benutzers
Jamikus
myCSharp.de - Member



Dabei seit:
Beiträge: 251
Herkunft: Oberhausen (NRW)

beantworten | zitieren | melden

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.
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Jamikus am .
private Nachricht | Beiträge des Benutzers
Reaper_97
myCSharp.de - Member



Dabei seit:
Beiträge: 13

Themenstarter:

beantworten | zitieren | melden

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

Moderationshinweis von Abt (08.10.2019 - 16:07:39):

Keine Full Quotes
[Hinweis] Wie poste ich richtig?

private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4132

beantworten | zitieren | melden

Kennst du schon [FAQ] Warum blockiert mein GUI?
Du darfst niemals im Hauptthread (UI-Thread) die Anwendung warten lassen.
private Nachricht | Beiträge des Benutzers
Reaper_97
myCSharp.de - Member



Dabei seit:
Beiträge: 13

Themenstarter:

beantworten | zitieren | melden

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?

Moderationshinweis von Abt (08.10.2019 - 16:07:48):

Keine Full Quotes
[Hinweis] Wie poste ich richtig?

private Nachricht | Beiträge des Benutzers
vbprogger
myCSharp.de - Experte

Avatar #avatar-1820.gif


Dabei seit:
Beiträge: 1723
Herkunft: NRW/DE

beantworten | zitieren | melden

Zitat von Reaper_97
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.
---------
Bemerkung: ich beantworte keine Fragen via PM, denn das Forum soll ja was davon haben!
private Nachricht | Beiträge des Benutzers
Reaper_97
myCSharp.de - Member



Dabei seit:
Beiträge: 13

Themenstarter:

beantworten | zitieren | melden

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

Moderationshinweis von Abt (08.10.2019 - 16:07:21):

Keine Full Quotes
[Hinweis] Wie poste ich richtig?

private Nachricht | Beiträge des Benutzers
vbprogger
myCSharp.de - Experte

Avatar #avatar-1820.gif


Dabei seit:
Beiträge: 1723
Herkunft: NRW/DE

beantworten | zitieren | melden

Zitat von Reaper_97
Ja danke dafür aber wie soll ich dass hier machen:?
https://www.codeproject.com/Articles/449594/Progress-Bars-Threads-Windows-Forms-and-You
Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.
---------
Bemerkung: ich beantworte keine Fragen via PM, denn das Forum soll ja was davon haben!
private Nachricht | Beiträge des Benutzers
Reaper_97
myCSharp.de - Member



Dabei seit:
Beiträge: 13

Themenstarter:

beantworten | zitieren | melden

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.

Moderationshinweis von Abt (08.10.2019 - 16:07:28):

Keine Full Quotes
[Hinweis] Wie poste ich richtig?

private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4132

beantworten | zitieren | melden

Dann zeige noch mal deinen aktuellen Code mit dem Timer.
private Nachricht | Beiträge des Benutzers
Reaper_97
myCSharp.de - Member



Dabei seit:
Beiträge: 13

Themenstarter:

beantworten | zitieren | melden

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();
        }
    }
}
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4132

beantworten | zitieren | melden

So sieht der Code doch ganz gut aus. Oder gibt es noch Probleme damit?
private Nachricht | Beiträge des Benutzers
Reaper_97
myCSharp.de - Member



Dabei seit:
Beiträge: 13

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16098

beantworten | zitieren | melden

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

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Reaper_97
myCSharp.de - Member



Dabei seit:
Beiträge: 13

Themenstarter:

beantworten | zitieren | melden

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

Ä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!");
        }
    }
}
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16098

beantworten | zitieren | melden

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
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Reaper_97
myCSharp.de - Member



Dabei seit:
Beiträge: 13

Themenstarter:

beantworten | zitieren | melden

Zitat von Abt
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.
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4132

beantworten | zitieren | melden

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.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16098

beantworten | zitieren | melden

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.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Reaper_97
myCSharp.de - Member



Dabei seit:
Beiträge: 13

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16098

beantworten | zitieren | melden

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.
Zitat von Reaper_97
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.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Reaper_97
myCSharp.de - Member



Dabei seit:
Beiträge: 13

Themenstarter:

beantworten | zitieren | melden

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.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Reaper_97 am .

Moderationshinweis von Abt (08.10.2019 - 20:28:14):

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

private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16098

beantworten | zitieren | melden

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?

- Mit Hilfe eines simplen Tasks (der sich auch ordentlich abbrechen lassen würde, Threads können das nicht) kann man die Abfrage auslagern und nichts blockiert mehr
- Die Controls lassen sich dann via Invoke aktualisieren ( [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke) )
- Statt einer Endlosschleife nehme ich einen Timer (via Reactive Extension Observable)

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
Zitat von Reaper_97
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.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Stefan.Haegele
myCSharp.de - Member

Avatar #avatar-3068.jpg


Dabei seit:
Beiträge: 456
Herkunft: Untermeitingen

beantworten | zitieren | melden

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?)
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4132

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers