2017-12-04 7 views
0

yield repeatを使用して、非決定論的な反復のセットを使用してデータを処理しています。私は処理を開始したいが、条件がヒットした後(例えば、バイトサイズ)ループを壊し、処理を続ける新しいスレッドに列挙子を渡し、それまで処理された結果を返す。C#yield return enumerator、途中から続行

実際、私は終わりの前に勃発する可能性のあるforeachループを持っています。 IEnumerableを新しいスレッドに渡すにはどうすればいいですか?

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 

} 

所望の出力:1 2 3 4 5 6

実際の出力:1 2 3 1 2 3 4 5 6

はありがとうございました。

+0

もっと複雑なもの(現在の位置を追跡するタイプ)が必要な場合や、他のスレッドで実行されるコードにスキップする項目の数を渡す必要がある場合。 – juharr

+2

@juharr:いいえ。列挙子が必要です。 – SLaks

+1

@SLaksそれでも、それを適切に処分するよう注意する必要があります。 – juharr

答えて

4

実際にIEnumerable<T>のインターフェイスを見てください。

IEnumerable<T>は完全にステートレスです。 GetEnumerator()メソッドが公開されています。ステートフルな列挙子は、どこにいるのかを把握することができます。

2つのループの間に同じエニューザー atorインスタンスを渡す必要があります。 foreachIEnumerable<T>(またはそれに類する)でしか動作しないため、IEnumerator<T>を直接使用するwhileループに置き換える必要があります。

すべてのコードパスにIEnumeratorを配置してください(そうでない場合はfinallyまたはusingブロックが実行されません)。

-1

ステートメントが独自のThreadFuncにあるかどうかを確認する必要があります。 メイン関数でチェックすると、スレッド関数がそれを中断しているため動作していません。

関連する問題