C# Threadsichere Liste in Net 3.5 inkl. Eventtrigger

BranX

Newbie
Registriert
Juni 2015
Beiträge
3
Guten Morgen,

Ich möchte die Daten mehrere USB/HID Geräte in eine Liste eintragen und das muss in Net 3.5 geschehen.
Ich habe in einer Tabelle bestimmte Eigenschaften von Geräten gespeichert, treffen diese Eigenschaften zu, bekommt jedes Gerät einen eigenen Thread in dem ein Event getriggert wird, sobald Daten anliegen.
Dise Daten sollen nun in eine Liste geschrieben werden.
Anschließend soll ein Event getriggert werden, welches die Daten in einer Form anzeigt.

ConcurrentQueue gibt es erst ab 4.0, fällt somit also weg.
Sollte ich einen BackgroundWorker nutzen und in diesem dann die Liste mit den Daten füllen und vorher die Liste "locken" ?
Oder gibt es bessere Alternativen zur Umsetzung?


Mit freundlichen Grüßen und vielen Dank.

BranX
 
Leider verliere ich meine Werte was wohl am neuen Thread liegen dürfte.
Also ich erstelle einen neuen Thread und dieser läuft solange, bis irgendein Error am Gerät festgestellt wird. Danach wird meine While Schleife beenden und der Thread gestoppt.

Kommen Daten rein, überprüfe ich, von welchem Gerät sie kommen und schreibe die Daten in eine Liste. Die Liste kommt dann aus der Klasse, welche das Gerät wiederspiegelt.

Die Initialisierung erfolgt so:
In einer Winform Klasse erstelle ich ein Object von meiner Event Klasse und erzeuge ein Event.

Code:
MyClass Machauf= new MyClass();

Eventklasse EK = new Eventklasse();
EK.GeräteEvent += new Eventklasse<DatenListe>(this.MeineDaten);

Machauf.Gerät(EK);

delegate void d_Daten(object sender, DatenListe e)
private void MEineDaten(object sender Datenliste e)
{
if InvokeRequired etc.... zeige Daten an.
}

Machauf
Code:
Datenliste Daten = new Datenliste(Eventklasse events);

....
Eventklasse

Code:
public event Eventhandler<DatenListe> GeräteEvent;

public void BekommeDaten(List<byte> meineListe)
{
try{
if(GeräteEvent != null)
{
GeräteEvent (this, new DatenListe{ Liste = meineListe;});
}
catch....
}

Datenliste

Code:
public class Datenliste : EventArgs
{
public BackgroundWorker _BGW;
private Eventklasse meinEvent;
AutoresetEvent ARE = new AutoresetEvent (false);

private readonly object lock = new object();
public List<byte> Liste  = new List<byte>();

public Datenliste(Eventklasse events)
{
meinEvent = events;
StartBGW();
}

private void StartBGW(){
            if (_BGW== null)
            {
                _BGW= new BackgroundWorker();
                _BGW.DoWork += new DoWorkEventHandler(BGW_Daten);
                _BGW.WorkerReportsProgress = true;
                _BGW.WorkerSupportsCancellation = true;

                if (_BGW.IsBusy == true)
                {
                    _BGW.CancelAsync();
                }
                else
                {
                    _BGW.RunWorkerAsync();
                }
            }
}

        private void BGW_Daten(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker_bgw = sender as BackgroundWorker;
            while (true)
            {
                if (_bgw.CancellationPending == true)
                {
                    e.Cancel = true;
                    return;
                }
                else
                {
                    if (ARE.WaitOne())
                    {
                        meinEvent .BekommeDaten(getList());
                    }
                }
            }
        }
        private List<byte> getList()
        {
            lock (locker)
                return Liste;
        }

        public void Add(byte value)
        {
            lock (locker)
            {
                Liste.Add(value);               
            }
            ARE.Set();
        }
}

Der Fehler kommt nun, wenn ich die Liste befüllen will:
Wie gesagt, es wurde ein neuer Thread erstellt, Daten kommen an und ich schreibe diese DAten in eine Liste:

Code:
private Datenliste;
...
   foreach (byte by in Datenkommenrein)            
                Datenliste.Add(by);

// Fehlermeldung: Die Klasse Datenliste ist null.

An der Stelle verliere ich meine Initialisierung aus der Machauf Klasse.
Gibt es eine oder mehrere Ideen/Tipps für eine bessere Umsetzung?

Vielen Dank
 
Ich kann zwar kein C# und möglicherweise liege ich falsch, aber für mich sieht es so aus, als würdest du keine Instanz von Datenliste erstellen, sondern direkt mit der Klasse selbst arbeiten und die Methoden statisch aufrufen. Das geht natürlich in die Hose, wenn diese Methoden instanzgebunden sind.
 
Zuletzt bearbeitet:
Code:
private Datenliste;
Das ist kein valider Code. Soll das eine private Variable vom Typ Datenliste sein oder eine Liste mit dem Namen Datenliste? Dem Zugriff nach vermute ich letzteres? Der fehlerhafte Code ist aber ein anderer als in der Machauf-Klasse?

Gewöhne dir an Variablennamen klein zu schreiben, sonst verwechselt man die schnell mit Klassen oder Properties.

Das lock() in Datenliste.getList macht auch nicht das, was du vermutlich denkst. Entweder du ersetzt diese durch ein GetItem oder erstellst eine Kopie der Liste. Und das public vor List<byte> Liste unbedingt in ein private ändern.
 
Vielen Dank für die Antworten. Meine Werte hatte ich verloren weil ich an einer Stelle die Klasse neu initialisiert hatte.

Ich hole mir die Liste nun so:

Code:
        public List<byte> getList()
        {
            lock (locker)
                Liste   = new List<byte>(Liste _temp);
            return Liste ;
        }

Bis jetzt scheint das so zu klappen. Die Liste hole ich mir erst wenn das Event im BGW getriggert wurde.
 
Code:
Liste   = new List<byte>(Liste _temp);
Ich bin zwar nicht auf dem neuesten Stand der Technik aber das sieht nicht nach validen Code aus.
Es sieht außerdem so aus, als ob du nur die Liste intern kopierst und das Original verwirfst. Das eigentliche Problem, dass die Liste nicht threadsicher bearbeitet wird, bleib bestehen.
 
Zurück
Oben