Laden...

Methodenzugriffe mit Verwendung von mehreren Backgroundworkers (als Service)

Erstellt von Pioneer17 vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.063 Views
P
Pioneer17 Themenstarter:in
148 Beiträge seit 2007
vor 14 Jahren
Methodenzugriffe mit Verwendung von mehreren Backgroundworkers (als Service)

Hallo zusammen

benötige wieder mal euere Hilfe.

Ist Situation:
In einem Dienst lasse ich in einer variablen Anzahl von Backgroundworkers neue Instanzen von einer Klasse laufen.
In dieser Klasse werden Anweisungen ausgeführt die anschliessend von einer weiteren Methode in einer anderen Klasse wieder verwertet werden sollen.


class A
{
...
 private void Anweisung()
 {
      Backgroundworker[] a = new Backgroundworker[10];
      ...
      for(...)
      {
          ....
          a[i].RunWorkerAsync(string xxx)
      }      
 }

 private void DoWork(object sender, DoWorkEventArgs e)
 {
     ...
     B = new B(e.Argument.ToString());
 }

 public static void Ausführen(string s)
 {
    ...//in diese Methode werden von den verschiedenen Backgroundworkers her die
       // verarbeiteten Daten übergeben.
    
    for(...)
    {
         //weitere neue Backgroundworker[]
        ...
        backroundworker b.RunWorkerAsync(s);
       ...
    }
 }
}
class B
{
   ...
   //verarbeitet etwas
   string state = "xxx";
   a.Ausfühen(state);
}

Ich hoffe es ist mit diesem Beispiel einbisschen deutlicher wie die Struktuer aufgebaut ist.

Das Problem liegt auf der Hand.
Es kann sein, dass wärend der Verarbeitung der Variable s bereits neue Daten von Backgroundworker a in die Variable s geschrieben werden (neue Aufrufe).

Somit habe ich das Problem, dass nicht alle Daten korrekt in Backgroundworker b verarbeitet werden.
Ich habe bereits verschiedene Dinge mit lock() versucht, aber bis jetzt nicht zu einem genügenden Resultat gefunden.

Hmm, hoffe es einigermassen verständlich ist was mein Problem ist.

Danke für eure Hilfe

2.223 Beiträge seit 2005
vor 14 Jahren

Hallo Pioneer17,

was hältst Du denn von einer Queue basierte Vorgehensweise?

BackGroundWorker a füllt die Queue und b holt die Daten aus der Queue und verarbeitet diese Eingaben.

Damit wäre sichergestellt das der backgroundworker b alle Daten verarbeiten kann

Viele Grüße
Lars

3.971 Beiträge seit 2006
vor 14 Jahren

Warum das ganze immer so umständlich?


public delegate void AusführenDelegate(string s);
public void Ausführen(string s) {
  ...

  lock (this.m_lck) {
    this.m_current++;
  }
}

/* Gemeinsam genutzte Klassenvariable */
private object m_lck = new Object();
private int m_current = 0;

/* Einzelner Asynchroner Aufruf */
var d = new AusführenDelegate(Ausführen);
d.BeginInvoke("xxx", null, r => d.EndInvoke(r));

/* Asynchroner Aufruf, anschließend warten bis alle beendet wurden */
var d = new AusführenDelegate(Ausführen);
var results = new IAsyncResult[10];
for (var i=0; i<results.length; ++i) {
  results[i] = d.BeginInvoke("xxx", null, null);
}
for (var i=0; i<results.length; ++i) {
  d.EndInvoke(results[i]);
}


Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo Pioneer17,

Synchronisierung löst man nicht eben nebenbei, in dem man hier und dort ein paar locks einfügt. Das ist ein Thema, in das man sich gründlich einarbeiten muss, damit alles passt. Siehe z.B. SyncQueue <T> - Eine praktische Job-Queue, um einen Eindruck zu bekommen, was für ungewöhnliche Konstellationen man berücksichtigen muss, wenn man nebenläufig programmiert. Schau dir daher das Thema Synchronisierung in Ruhe und gründlich an.

Einen ersten Einstieg bietet: [Artikel] Multi-Threaded Programmierung.

herbivore

P
Pioneer17 Themenstarter:in
148 Beiträge seit 2007
vor 14 Jahren

Besten Dank für die Antworten.

Auf die schnelle konnte ich es jetzt mit der Queue lösen -> Dank an Lars Schmitt

@kleines_eichhoernchen, herbivore
ist definitiv die bessere Lösung. Wie du herbivore bereits gesagt hast, ist das aber etwas was nicht so rasch nebenbei gemacht wird, d.h. ich muss mich tiefer damit auseinander setzen. Da ich momentan aber erstmal froh bin dass es jetzt zufriedenstellend funktioniert werde ich es vorerst so belassen.

Aber besten dank für den Artikel "Multi-Threaded Programmierung" der ist echt super und gut beschrieben.

Ich gehe davon aus, dass wenn ich den Code umbauen würde einen Performance-Schub bekommen würde. Momentan werden bei mir jetzt pro Sekunde "nur" 2-3 Meldungen von den Backgroundworkers versendet.

5.299 Beiträge seit 2008
vor 14 Jahren

kl. anmerkung @kleines_eichhoernchen]

  
d.BeginInvoke("xxx", null, r => d.EndInvoke(r));  
  

Das ist schon hübsch, geht aber nochn bischen hübscher:


d.BeginInvoke("xxx", null, d.EndInvoke);

d.EndInvoke _ist _ein passender AsyncCallback.

hups, der Callback ist ja im falschen Parameter, oder?, also


d.BeginInvoke("xxx", d.EndInvoke, null);

Der frühe Apfel fängt den Wurm.

3.971 Beiträge seit 2006
vor 14 Jahren

d.EndInvoke ist ein passender AsyncCallback.

Danke, kannte ich noch nicht.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...