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
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
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?
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...
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.
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.
// Beim Start muss erstmal der Ringbuffer befüllt werden.
4
if(hilfeee==211)
5
{
6
for(inti=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(inti=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
intRecievedLine=0;
2
3
//Test-Serielle-Schnittstelle: - Backgroundworker
4
while(serialPort.BytesToRead!=0)// Abfragen, ob ein 2tes Byte bereits im Buffer ist.
// 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.
[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.
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.
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?
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
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.
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(inti=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)
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^^
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.
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
So Sorry, war am Wochenende nicht motiviert am Programm zu arbeiten.
1
voidFilterung()
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(inti=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(inti=(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
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
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
voidFilterung()
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.
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