PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme mit Multithreading und statischen Methoden/Variablen


moBi
2009-05-31, 22:10:27
Hallo,

eins Vorweg, für mich war/ist das ziemliches Neuland und ich muss das im Rahmen meiner Tätigkeit als Werkstudent machen.

Ich würde gerne einen an sich autarken Codeblock mehrfach parallel ausführen lassen, nur machen mir statische Methoden und Variablen zuverlässig einen Strich durch die Rechnung. Mir ist die grundsätzliche Problematik bei Multithreading mit statischem Zeug klar und würde daher gerne das statische Zeug los werden, aber ich weiß nicht so recht wie.

Hier mal die folgende Situation und meine bisherige Lösung: Ich musste einen bereits vorhandenen Algorithmus, der in C geschrieben wurde in eine Windows-Forms Anwendung, welche mit C# realisiert werden sollte einbinden. Ich habe mir dazu einen Wrapper in managed C++ geschrieben, da ich den C-Code nicht in eine DLL packen darf.

Das "Problem" ist das Interface des C-Codes. Der Datenaustausch erfolgt mit "extern" Funktionen, die ich erst impementieren muss. Diese "extern" Funktionen habe ich dann mittels "extern C" in managed C++ implementiert, sinngemäß etwa so:


int getParameter(void) //Algo bekommt Parameter
{
return Wrapper::value;
}

void sendResult(int result) //Algo liefert Ergebnisse
{
Wrapper::result = result;
}

void initAlgoManaged() //Initialisierung des Algos von C# aus
{
initAlgoC();
}

void mainTaskManaged() //Auswerten Starten
{
mainTaskC();
}


Wobei die Wrapperklasse so aus sieht:


class ref Wrapper
{
public:
static int value;
static int result;

static void initAlgoManaged();
static void mainTaskManaged();
}


Unter C# dann so:


using Wrapper;

class WForm
{
Wrapper.initAlgoManaged();

while(reader.EndOfLine != True)
{
zeug = reader.ReadLine();
Wrapper.value = zeug;
Wrapper.mainTaskManaged();
erg = Wrapper.result;
}
}


Um das ganze zu beschleunigen und da hier überall mindestens Dualcore CPUs verbaut sind wollte ich jetzt einfach zwei Dateien parallel auswerten lassen. Allerdings funktioniert das nicht, da wegen dem static jeder Thread auf die gleichen static Parameter zugreift und deswegen nur noch Müll herauskommt, aber dafür deutlich schneller ist.:biggrin:

Ich sehe da jetzt zwei Möglichkeiten: Entweder sich schaffe es irgendwie das ganze static Konstrukt zu umhüllen, so dass bei einem "new" auch wirkllich jeder Thread auf seinen eigenen "static Speicher" zugreifen kann. Die Alternative wäre, ganz auf static verzichten zu können, aber da sehe ich keine Möglichkeit, bzw. hatte noch keinen Erfolg und auch google konnte ausnahmsweise nicht weiter helfen.

Dass das unmöglich sein soll kann ich nicht glauben, aber der Funke will auch nicht überspringen.:redface:

Bietchiebatchie
2009-05-31, 22:22:57
Ich verstehe ehrlich gesagt absolut nicht, wieso du überhaupt irgendwas static brauchst - falls aus irgendeinen (mir gerade nicht ersichtlichen) Grund das ganze nötig ist kannst du mit Hilfe von System.ThreadStaticAttribute sicherstellen, dass statische Felder pro Thread erzeugt werden.

Ectoplasma
2009-06-01, 10:43:57
Ich verstehe zwar auch nicht, wozu die Methoden static sein sollen, aber da dieser Umstand bei dir gegeben zu sein scheint, kann ich nur folgende Lösung vorschlagen. Gebe den Methoden doch ein Handle mit. Das ist nichts weiter als eine Struktur-Instanz, bzw. eine Rererenz auf deine Thread Daten. Also für jeden Thread erzeugst du mit new eine Struktur mit threadrelevanten parametern und übergibst diese einfach als Funktionsargument an deine Methoden.

moBi
2009-06-01, 14:36:50
Erstmal danke für eure Antworten, das mit dem Attribut hört sich schon mal sehr gut an.:smile:

Ich würde es ja auch gerne ohne static machen, aber der Compiler lässt mich nicht. Wenn ich das static weg lasse und nur public mache, dann kann ich nicht mehr auf die Felder/Methoden zugreifen, weil noch kein Objekt existiert, dass dieses Feld überhaupt hat.

So funktioniert es ohne static, aber das hilft halt nicht:


void sendResult(int result) //Algo liefert Ergebnisse
{
Wrapper wrap = new Wrapper();
wrap.result = result;
}