For Schleife Ergebnis in Überlauf mit Task.Run oder Task.Start

8

habe ein Problem, hoffe, dass mir jemand helfen kann.

Ich versuche 4 Task in einer Schleife zu starten, bekomme aber eine ArgumentOutOfRangeException:

%Vor%

Die Schleife erhält einen Überlauf, weil i = 4

ist

Wenn ich die Tasks ohne Schleife starte, laufen sie ohne Probleme:

%Vor%

weiß nicht warum? Die Tasks GetData von einer Siemens SPS über Socket Connection. Die SPS unterstützt bis zu 32 Verbindungen. Ich erhalte 200 Bytes pro Verbindung.

%Vor%

irgendeine Idee?

Grüße Sam

    
Sam 22.10.2015, 07:49
quelle

2 Antworten

12

Es wird wahrscheinlich durch eine Schließungsproblem .

Versuchen Sie Folgendes:

%Vor%

Was wahrscheinlich passiert, ist, dass wenn der letzte Thread gestartet wird, die Schleife i bereits auf 4 erhöht hat, und das ist der Wert, der an GetData() übergeben wird. Den Wert von i in eine separate Variable index einzufangen und stattdessen zu verwenden, sollte das Problem lösen.

Als Beispiel, wenn Sie diesen Code versuchen:

%Vor%

es wird Ihnen oft diese Art von Ausgabe geben:

%Vor%

Ändern Sie diesen Code in:

%Vor%

und Sie erhalten etwas wie

%Vor%

Beachten Sie, wie es NOCH NICHT NOTWENDIG IST! Sie sehen alle korrekten Werte ausgedruckt, aber in einer unbestimmten Reihenfolge. Multithreading ist tricky!

    
Matthew Watson 22.10.2015, 07:55
quelle
-1
  

In C # 5 befindet sich die Schleifenvariable einer foreach logisch innerhalb der Schleife und daher schließen sich Closures bei jeder neuen Kopie der Variablen . Die "for" -Schleife wird nicht geändert.

Ein anderer Weg ist der:

  1. Erstellen Sie Aufgaben
  2. Führen Sie die Aufgaben aus.
  3. Warten Sie, bis alle Aufgaben beendet sind.

Der Demo-Code wie folgt:

%Vor%

AUSGABE:

%Vor%

Hinweis: Es ist new Task<byte[]>(GetData,i); nicht new Task<byte[]>(()=>GetData(i));

  

() = & gt; v bedeutet "gebe den aktuellen Wert der Variablen v zurück", nicht "gebe den Wert zurück v war zurück, als der Delegat erstellt wurde". Verschlüsse schließen sich über Variablen, nicht über Werte .

Die new Task<byte[]>(GetData,i); haben also kein Closures Problem

    
huoxudong125 22.10.2015 08:15
quelle

Tags und Links