Forum: PC-Programmierung Backgroundworker mit C#.net


von Anti-Programmierer (Gast)


Lesenswert?

Kennt jemand ein gutes Tutorial zum Backgroundworker?
Ich möchte damit eine Filterung relisieren.
Habe versucht die Daten ohne Worker zu filtern, jedoch ist ab Beginn der 
Filterung das Programm zu langsam geworden und es hat unglaublich 
gehakt.
Nun muss ich das auslagern in diesen Worker.
Doch wie funktioniert das?
Ich habe immer 2 Werte die ich diesem übergebe. Das Filter ist 211 
Ordnung, d.h ich muss insgesamt 211 float Multiplikationen durchführen.
Wie übergebe ich nun die Daten, und bekomm ich so etwas wie einen 
Interrupt, wenn ein Filterwert fertig ist?. Muss die dann anschließend 
in ein Diagramm schreiben.
Über Hilfe wäre ich sehr dankbar

mfg
Anti-Programmierer

von Peter II (Gast)


Lesenswert?


von Anti-Programmierer (Gast)


Lesenswert?

Kannst du mir auch sagen, auf was Konkret ich da achten muss?
Die Seite hab ich schon durchgeschaut, aber mir ist noch ned wirklich 
klar wie ich das mit dem übergeben und dem multiplizieren machen muss

von Peter II (Gast)


Lesenswert?

Anti-Programmierer schrieb:
> Kannst du mir auch sagen, auf was Konkret ich da achten muss?

nein nicht wirklich, weil ich ja nicht weiss was du kannst. Ich arbeitet 
selber aber nur mit normaln Thread und nicht mit dem Backgroundworker.

Hast du noch nie mit Thread gearbeitet?

von Anti-Programmierer (Gast)


Lesenswert?

Nein
Habe das für ein Schulprojekt benötigt und mir selbst beigebracht und 
nun steh ich halt vor dem Problem, dass ein paar Sachen Macken machen.
Hab grad überprüft. Ich mach eine Double Multiplikation und das 211 mal, 
das dauert halt ewig lange, und ich muss das nun irgendwie optimieren da 
ich sonst nicht zusammenkomme...

von Peter II (Gast)


Lesenswert?

Anti-Programmierer schrieb:
> Ich mach eine Double Multiplikation und das 211 mal,
> das dauert halt ewig lange, und ich muss das nun irgendwie optimieren da
> ich sonst nicht zusammenkomme...

was ist bei dir ewig lange? Sotwas sollte doch in ein paar ms erledigt 
sein.

Mit thread könnte man es so machen.

Man speicher die Werte in einer Liste
Starten den Thread und übergibt ihm die Liste
Wenn der Thread fertig ist, dann ruft er über delcates eine Funktion aus 
dem hauptprogramm auf, und dieser zeigt dann die Infos an.
Thread beendet sich

Zeig doch mal den code mit der Berechnung und ein paar zahlen wie lange 
es dauert.

von bluppdidupp (Gast)


Lesenswert?

Beim Aufruf von .RunWorkerAsync() kann man als Parameter ein Objekt 
übergeben.
Im Worker selbst (DoWork) kann man über e.Argument an das Objekt 
drankommen.
Was auch immer im Worker produziert wird, packt man dann in e.Result 
rein.
Darauf kann man wiederrum in RunWorkerCompleted zugreifen.

Zwischenergebnisse könnte man über ReportProgress raushauen.

von Anti-Programmierer (Gast)


Lesenswert?

1
 {
2
            #region Filter
3
            // Beim Start muss erstmal der Ringbuffer befüllt werden.
4
            if (hilfeee == 211)
5
            {
6
                for (int i = 0; i < 210; i++)
7
                {
8
                    Ringbufferx[i] = Ringbufferx[i + 1];
9
                    Ringbuffery[i] = Ringbuffery[i + 1];
10
                    if (hilfeee <= 104)
11
                        Atmungung[i] = Atmungung[i + 1];
12
                }
13
                Ringbufferx[210] = x;
14
                Ringbuffery[210] = y;
15
                Atmungung[104] = x;
16
17
18
            }
19
            if (hilfeee <= 210)
20
            {
21
                Ringbufferx[hilfeee] = x;
22
                Ringbuffery[hilfeee] = y;
23
24
                if (hilfeee <= 104)
25
                    Atmungung[hilfeee] = y;
26
                    
27
28
                hilfeee++;
29
            }
30
            else
31
            {
32
                for (int i = 0; i < 211; i++)
33
                {
34
                    xf = Koeffizienten[i] * Ringbufferx[i];
35
                    yf = Koeffizienten[i] * Ringbuffery[i];
36
                    CreateGraphHerz();
37
38
                }
39
            }

Hier führe ich meine Filterung durch.
Solange ich noch keine 211 Messwerte erhalten habe( also hilfeee < 211 
ist), aktualisiert er meine Diagramme so, dass die Messwerte schön 
flüssig dargestellt werden.
gehts dann aber weiter und es kommen weitere Messwerte hinzu, beginnt 
das unglaublich zu hacken und meine Diagramme werden nur mehr alle 
800-1000ms aktualisiert( vorhin ca alle 120ms)

Die Daten empfange ich mit:
1
 int RecievedLine = 0;
2
3
            //Test-Serielle-Schnittstelle: - Backgroundworker
4
            while (serialPort.BytesToRead != 0) // Abfragen, ob ein 2tes Byte bereits im Buffer ist.
5
            {                                   // Wenn ja, wird dies auch ausgelesen
6
                RecievedLine = serialPort.ReadByte();
7
                    h2 = h2 + 1;
8
                    if (h2 == 4)
9
                        h2 = 1;
10
                
11
                lbRecieved.Invoke(lbRecievedDelegate, new object[] { RecievedLine });
12
            }

Die Datei-Auswertung folgt dann:
1
 void InvokeLBRecieved(int Data)
2
        {
3
                #region Daten auswerten
4
               h1 = Data - '0';
5
6
              // this.Text = Convert.ToString(serialPort.BytesToRead);
7
8
               if (count1 == 0)
9
               {
10
                   if (h2 == 1)
11
                       Wert = h1 * 100;
12
                   if (h2 == 2)
13
                       Wert = Wert + h1 * 10;
14
                   if (h2 == 3)
15
                   {
16
                       Wert = Wert + h1;
17
                       h3 = Wert;
18
                       count1 = 1;
19
                   }
20
               }
21
               if (count1 == 1 & count3 == 0)// Bettsensor links hinten //ADC1
22
                {
23
                    hlihiP = h3;
24
                   // h2 = 0;
25
                    // Hier wird die Berechnung durchgeführt!
26
                    // 3 Empfangene Bytes ergeben 1nen Messwert! 
27
                    // Der erste empfangene Wert mit dem MSB muss ganz nach links geschoben werden
28
                    // Da wir nur 19 der 24 Bits für unsere Daten zur verfügung haben, müssen wir diese noch mit 5 nach rechts shiften.
29
                    if (count2 == 1) 
30
                    {
31
                       lihiP = (hlihiP << 16);
32
                    }
33
                    if (count2 == 2)
34
                    {
35
                        lihiP |= (hlihiP << 8);
36
                        
37
                    }
38
                    if (count2 == 3)
39
                    {
40
                           lihiP = lihiP + hlihiP;
41
                           lihiP = (lihiP >> 5);
42
                           lihiP = (lihiP << 5);
43
                           
44
                           // Durch den Höchswert dividieren und mit einem Wert( 1V?) multiplizieren, float, Variable
45
                           //Typecasten
46
                          // CreateGraphHerz();
47
                           count2 = 0;
48
                       //    tw.WriteLine(lihiP);
49
                           CreateGraphAll();
50
                           count3++;
51
                    }
52
                       count1 = 0;
53
                       count2 ++;
54
                }
Was mich wundert ist, dass er dann CreateGraphAll(); nur alle Sekunden 
oder so macht.
Meines Verständnisses sollte doch der Event-Handler von Data-Received 
die Filtermultiplikation unterbrechen und die Dateiauswertung machen 
oder liege ich da irgendwo falsch?
Die Dateiauswertung von oben wird ab dem if(count1 == 1 & count3 == 0) 
noch  5 mal fast gleich, bis auf die Abfragen durchgeführt. Erst beim 
letzten dieser Blöcke rufe ich meine Filterungsfunktion auf.

von Peter II (Gast)


Lesenswert?

[c]
if (hilfeee == 211)
            {
                for (int i = 0; i < 210; i++)
                {
                    Ringbufferx[i] = Ringbufferx[i + 1];
                    Ringbuffery[i] = Ringbuffery[i + 1];
                    if (hilfeee <= 104)
                        Atmungung[i] = Atmungung[i + 1];
                }
                Ringbufferx[210] = x;
                Ringbuffery[210] = y;
                Atmungung[104] = x;


            }
[c]

das ist doch schon mal sehr fragwürdig. Warum die Abfrage
if (hilfeee <= 104)

Wenn vorher schon if (hilfeee == 211) abgefragt wird?

Dann solltest du dich mal wirklich mit dem Thema ringpuffer auseinander 
setzen. Er heist so weil es ein ring ist. Du schiebst du daten aber 
immer durch die gegend - warum? merk dir doch einfach die aktuelle 
Position dann liegen ebend die daten von 100..210..0..99 aber dafür 
sparst du dir die aktion 400werte zu verschieben.

von Peter II (Gast)


Lesenswert?

1
for (int i = 0; i < 211; i++)
2
                {
3
                    xf = Koeffizienten[i] * Ringbufferx[i];
4
                    yf = Koeffizienten[i] * Ringbuffery[i];
5
                    CreateGraphHerz();
6
7
                }

das sieht auch merkwürdig aus, sicher das du CreateGraphHerz 211 mal 
aufrufen musst? Und globale variabeln sind auch nicht wirklich sinnvoll. 
Niemand sieht was mit xf oder yf passiert. Vermutlich verwendet 
CreateGraphHerz sie, aber das sieht niemand.
1
for (int i = 0; i < 211; i++)
2
{
3
   int xf = Koeffizienten[i] * Ringbufferx[i];
4
   int yf = Koeffizienten[i] * Ringbuffery[i];
5
   CreateGraphHerz(xf, xy);
6
}

würde die sache schon mal verständlicher machen.

von Anti-Programmierer (Gast)


Lesenswert?

Stimmt die Abfrage mit den 104 kann ich mir ersparen.
Naja damit schreibe ich den neuen Wert immer an die letzte Position des 
Ringbuffers, wie soll ich das sonst gestalten?

von Peter II (Gast)


Lesenswert?

Anti-Programmierer schrieb:
> Stimmt die Abfrage mit den 104 kann ich mir ersparen.
> Naja damit schreibe ich den neuen Wert immer an die letzte Position des
> Ringbuffers, wie soll ich das sonst gestalten?

nicht an die letze position, sondern an die nächste.

erst schreibst du von 0 bis 211 rein, dann machst du mit 0, 1, 2, 3, 4 
weiter und merkt dir die Stelle.

Wenn du also in der 4. Position etwas geschrieben hast, dann steht an 
der 5. Stelle der älteste Wert. Wenn du alle werte abfrage willst musst 
du dann also von 5 bis 211 und dann noch von 0 bis 4 durchgehen.

http://de.wikipedia.org/wiki/Warteschlange_%28Datenstruktur%29

von Anti-Programmierer (Gast)


Lesenswert?

Stimmt, an das hab ich noch gar nicht gedacht, erspart wirklich einiges. 
Danke

von Anti-Programmierer (Gast)


Lesenswert?

Oh Gott, so erst seh ich, dass das absoulter Schwachsinn ist^^.
xf ist ja die Summe aller Multiplikationen und das Diagramm muss ich 
auch erst danach aufrufen!
Das nervt mich jetzt^^ sicher schon 100mal drübergeschaut und das ist 
mir nie aufgefallen.

von Peter II (Gast)


Lesenswert?

Anti-Programmierer schrieb:
> xf ist ja die Summe aller Multiplikationen und das Diagramm muss ich
> auch erst danach aufrufen!

aber dann stimmt das ja überhaupt nicht.
1
for (int i = 0; i < 211; i++)
2
{
3
   xf = Koeffizienten[i] * Ringbufferx[i];

hier wird doch xf immer überschrieben, damit gewinnt nur der letzt wert. 
(Das könnte man dann auch schneller programmieren)

von Anti-Programmierer (Gast)


Lesenswert?

Jep, habs schon auf xf + Wert aus Multiplikation geändert.
Wie schneller gehts den? was ist dem am Effizientesten?
wäre froh wenn ich einfach die Funktion lassen kann und keinen 
BackgroundWorker machen muss^^

von Peter II (Gast)


Lesenswert?

Anti-Programmierer schrieb:
> Wie schneller gehts den? was ist dem am Effizientesten?

nein ist schon ok, ich meinte das alte falsche verhalten hätte man auch 
so schreiben können:

xf = Koeffizienten[211] * Ringbufferx[211];

ohne schleife. Aber das wolltest du ja gar nicht.

> wäre froh wenn ich einfach die Funktion lassen kann und keinen
> BackgroundWorker machen muss^^
bei den paar werten lohnt sich das auch nicht. das wird wenn man es 
richtig gemacht ein ein paar ms berechnet.

Kannst ja deinen code noch  mal zeigen, nach dem du die fehler entfernt 
hast.

von Anti-Programmierer (Gast)


Lesenswert?

Jo ich setz mich heute Abend ran und werd mal alle Fehler die ich finde 
ausbessern, ich stell ihn dann morgen rein damit du nochmal ein Auge 
drauf werfen kannst.
Ist es eig schneller wenn ich int64 anstatt von double verwende? ich hab 
zwar Koeffizienten die 0.000xxxxxxxxxxx Format haben, aber könnte diese 
Werte ja als ganzzahl nehmen und später noch ne Division durchführen

von Peter II (Gast)


Lesenswert?

Anti-Programmierer schrieb:
> Ist es eig schneller wenn ich int64 anstatt von double verwende?

spielt bei den paar zahlen keine rolle.

von Anti-Programmierer (Gast)


Lesenswert?

okay, danke

von Anti-Programmierer (Gast)


Lesenswert?

So Sorry, war am Wochenende nicht motiviert am Programm zu arbeiten.
1
void Filterung()
2
        {
3
            #region Filter
4
            // Beim Start muss erstmal der Ringbuffer befüllt werden.
5
            if (hilfeee <= 210)
6
            {
7
                Ringbufferx[hilfeee] = x;
8
                Ringbuffery[hilfeee] = y;
9
                hilfeee++;
10
            }
11
            else
12
            {
13
                if (hilfsindex >= 211)
14
                    hilfsindex = 0;
15
16
                xf = 0;
17
                yf = 0;
18
19
                for (int i = 0; i < (211 - hilfsindex); i++)
20
                {
21
                        xf = xf + Koeffizienten[i] * Ringbufferx[hilfsindex + i];
22
                        yf = yf + Koeffizienten[i] * Ringbuffery[hilfsindex + i];
23
                }
24
                for (int i = (211 - hilfsindex); i < 211; i++)
25
                {
26
                    xf = xf + Koeffizienten[i] * Ringbufferx[hilfsindex2];
27
                    yf = yf + Koeffizienten[i] * Ringbuffery[hilfsindex2];
28
                    hilfsindex2++;
29
                }
30
                CreateGraphHerz(xf, yf);
31
32
                Ringbufferx[hilfsindex] = x;
33
                Ringbuffery[hilfsindex] = y;
34
35
                hilfsindex2 = 0;
36
                hilfsindex++;
37
            }
38
            #endregion
39
        }

Denk ich mir das so richtig?
Habe ein Filter 211 Ordnung, d.h beim ersten if, schreibe ich das Filter 
erstmal voll.
Sobald es voll ist arbeite ich den else Zweig durch und führe dort die 
Filterung durch. Dann kommt der Ringbuffer( da bin ich mir ned sicher ob 
der so stimmt)  und danach wieder von Anfang an den Ringbuffer 
beschreiben, mit Hilfsindex als Hilfsvariable

von Peter II (Gast)


Lesenswert?

ich denke das kann man noch vereinfachen

[c]
bool init = false;

void Filterung()
{
   #region Filter

   Ringbufferx[hilfeee] = x;
   Ringbuffery[hilfeee] = y;

   hilfeee++;
   if (hilfeee >= 211) {
      init = true;
      hilfeee = 0;
   }

   if ( !init) {
      return;
   }

   xf = 0;
   yf = 0;
   for (int i = 0; i < 211); i++)
   {
      xf = xf + Koeffizienten[i] * Ringbufferx[hilfsindex + i];
      yf = yf + Koeffizienten[i] * Ringbuffery[hilfsindex + i];
   }
   CreateGraphHerz(xf, yf);

   #endregion
}

von Peter II (Gast)


Lesenswert?

so 2.Versuch
1
bool init = false;
2
3
void Filterung()
4
{
5
   #region Filter
6
7
   Ringbufferx[hilfeee] = x;
8
   Ringbuffery[hilfeee] = y;
9
10
   hilfeee++;
11
   if (hilfeee >= 211) {
12
      init = true;
13
      hilfeee = 0;
14
   }
15
16
   if ( !init) {
17
      return;
18
   }
19
20
   xf = 0;
21
   yf = 0;
22
   for (int i = 0; i < 211; i++)
23
   {
24
      xf = xf + Koeffizienten[i] * Ringbufferx[(i+hilfeee-1)%211];
25
      yf = yf + Koeffizienten[i] * Ringbuffery[(i+hilfeee-1)%211];
26
   }
27
   CreateGraphHerz(xf, yf);
28
29
   #endregion
30
}

von Anti-Programmierer (Gast)


Lesenswert?

hm danke, ich werde mir das mal durchdenken

von Anti-Programmierer (Gast)


Lesenswert?

Weist du zufällig auch noch, wie ich während des ersten füllen des 
Filters einen Ladebalken einfüge? Msdn hilft mir da nicht wirklich 
weiter. Blockt der Ladebalken mein Programm, bzw muss ich das nun in 
einem Backgroundworker machen?

mfg

von Peter II (Gast)


Lesenswert?

Anti-Programmierer schrieb:
> Msdn hilft mir da nicht wirklich
> weiter.
glaube ich nicht

> Blockt der Ladebalken mein Programm, bzw muss ich das nun in
> einem Backgroundworker machen?
warum sollte der Ladebalken dein Programm blockieren, im schlimmsten 
fall wird er nur nicht aktualisiert.

An was für einen Ladebalken hast du überhaupt gedacht?

1
void Filterung()
2
{
3
   #region Filter
4
5
   Ringbufferx[hilfeee] = x;
6
   Ringbuffery[hilfeee] = y;
7
8
   hilfeee++;
9
10
   LadeBalken++;

Evenutell müsstest du aber mal mehr von deinen code zeigen, dann man 
sieht ja nicht wie Filterung aufgerufen wird.

von Anti-Programmierer (Gast)


Lesenswert?

Die Filterung wird gleich nach der seriellen Schnittstelle aufgerufen. 
Danach muss natürlich erst mal das Filter initialisert, also gefüllt 
werden. Während das geschieht soll er mir eine neue Form aufmachen, in 
der nur der Ladebalken ist und mit so anzeigt, wie weit die 
Initialisierung abgeschlossen ist. Das dauert so ca 20 Sekunden.
Währenddessen soll mein Hauptfenster deaktiviert sein ( aber nicht 
ausgeblendet, also nur so grau, damit der Benutzer nichts machen kann) 
erst wenn das Filter gefüllt ist soll das Fenster wieder aktiv werden

von Anti-Programmierer (Gast)


Lesenswert?

Ich kann dir auch gerne den ganzen Programmcode senden wenn du willst, 
dann kannst du dir selbst davon ein Bild machen!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.