2017-12-04 4 views
0

Ich benutze Rendite zurück, um einige Daten zu verarbeiten, mit einem nicht-deterministischen Satz von Iterationen. Ich möchte mit der Verarbeitung beginnen, aber die Schleife beenden, sobald eine Bedingung (z. B. Bytegröße) erreicht wurde, den Enumerator an einen neuen Thread übergeben, der weiter verarbeitet wird, und dann die bisher verarbeiteten Ergebnisse zurückgeben.C# yield return enumerator, Fortsetzung von Teil der Weg durch

In der Tat habe ich eine foreach-Schleife, die ich wahrscheinlich vor dem Ende ausbrechen werde. Wie kann ich den IEnumerable an einen neuen Thread übergeben und von dort, wo ich aufgehört habe, fortfahren anstatt vom Anfang?

public static IEnumerable<String> Process() 
{ 
    // static values added for simplicity, but will be a variable number of returns 
    yield return "1"; 
    yield return "2"; 
    yield return "3"; 
    yield return "4"; 
    yield return "5"; 
    yield return "6";  
} 

List<String> main() 
{ 
    List<String> retVal = new List<String>(); 
    IEnumerable<String> strList = Process(); 

    foreach(String strItem in strList) 
    { 
     retVal.Add(strItem); 
     Console.WriteLine(strItem); 
     // Time to send something back and continue in a new thread 
     if (strItem.Equals("3")) 
     { 
      break; 
     } 
    }   

    new Thread(() => ThreadFunc(strList)).Start(); 
    return retVal; 
} 

public static void ThreadFunc(IEnumerable<String> strList) 
{ 
    List<String> retVal = new List<String>(); 
    foreach(String strItem in strList) 
    { 
     retVal.Add(strItem); 
     Console.WriteLine(strItem); 
    } 
    // Send the rest of the data 

} 

Wunsch Ausgang: 1 2 3 4 5 6

tatsächlicher Ausgang: 1 2 3 1 2 3 4 5 6

danken Sie.

+0

Sie benötigen etwas Komplexeres (ein Typ, der die aktuelle Position verfolgt) oder die Anzahl der Elemente, die an den Code übergeben werden, der im anderen Thread ausgeführt wird. – juharr

+2

@juharr: Nein; Sie brauchen nur einen Enumerator. – SLaks

+1

@SLaks Oder das, aber dann müssen Sie vorsichtig sein, um sicherzustellen, dass Sie es ordnungsgemäß entsorgen. – juharr

Antwort

4

Schauen Sie, was die IEnumerable<T> Schnittstelle tatsächlich tut.

IEnumerable<T> ist vollständig zustandslos; Es stellt nur eine GetEnumerator() Methode zur Verfügung, die Stateful Enumeratoren zurückgibt, die verfolgen, wo sie sind.

Sie müssen die gleiche Instanz zwischen Ihren beiden Schleifen übergeben. foreach kann nur unter IEnumerable<T> (oder ähnlich) arbeiten, also müssen Sie sie durch while Schleifen ersetzen, die IEnumerator<T> direkt verwenden.

Stellen Sie sicher, dass die IEnumerator in allen Codepatches zu entsorgen ist (andernfalls finally oder using Blöcke werden nicht ausgeführt).

-1

Sie sollten überprüfen, ob die Aussage in Ihrem eigenen ThreadFunc war! Wenn Sie es in der Hauptfunktion überprüfen, funktioniert es nicht, weil die Thread-Funktion es bricht.

Verwandte Themen