2012-01-07 14 views
1

(OBS:英語は母国語ではありませんが、この質問のタイトルは良いものではありませんが、質問自体を明確にするために努力しました)のはtsは高価な計算を行いyield return方法を使用して生成されたとしましょう -複数のアイテムが1つのスレッドで生成されるのを待つ

のは、私は多くのアイテムを持っているIEnumerable<T> tsがあり、各MoveNextメソッド()は非常に高価であると仮定しましょう。

コードのこの作品を見てみましょう。

var enumerator = ts.GetEnumerator(); 
while (true) { 
    T t = await TaskEx.Run<T>(() => enumerator.MoveNext() ? 
            enumerator.Current : 
            null); 
    if (t == null) break; 
    t.DoSomeLightweigthOperation(); 
} 

それは(私の場合、UIスレッドで、)メインスレッドをブロックせずに、非同期的に収集tsを消費します。問題は、それはtsの各項目の1つのスレッドを生成することです。ジョブ全体を実行するスレッドを1つだけ使用して同じことを行う(単純な)方法はありますか?

だから、ちょうど私が唯一つのスレッドを使用してこれらの項目を生成したい、自分自身を明確にするが、私はTask Sのコレクションのいくつかの種類(またはGetAwaiterと他のクラス)を取得する必要がありますするには、私は後にawaitをできるように、これらの項目のそれぞれの生成。

ThreadPool.QueueUserWorkItem(_ => 
{ 
    foreach(T t in ts) 
    { 
     t.DoSomeLightweigthOperation(); 
    } 
}); 

だけで、スレッドプールからのスレッド上で、それを通る:あなたがしたいすべてが別のスレッド上のTSを介して実行された場合

答えて

1

既存のソリューションは、各項目に1つのスレッドを生成しません使用することができますWPFを使用している場合。むしろ、各アイテムごとに1回、スレッドプールにキューイングされるスレッドプールワークアイテムを作成します。それぞれのMoveNextが実際に同じスレッドプールスレッドによって実行される(可能性もあります)可能性があります。

私はあなたの制約を考慮して、既存のソリューションがうまくいくと思います。

列挙型をすべて変更することができる場合は、IAsyncEnumerator<T>と考えると、Task<bool> MoveNext()というメンバーがあります。 IAsyncEnumerator<T>/IAsyncEnumerable<T>は、Ix_Experimental-Asyncの一部です。私はまた、Nito.AsyncExの一部であるほぼ同じIAsyncEnumerator<T>を書きました。非同期列挙は、実行しようとしているものに近い一致です。非同期列挙を記述するChannel9 videoがあります(ただし、APIはそれ以降わずかに変更されています)。

+0

OK、ありがとう。私のIEnumeratorはコンパイラによって書かれています。imはimを使ってyield returnメソッドを使用しているからです。非同期にする方法はありますか? – Player

+0

簡単にはありません。まだ組み込みの言語サポートはありません。あなた自身の非同期列挙子/列挙可能な実装を書いてそれに投稿する必要があります。 Ix_Experimental-Asyncには、使用できるビルディングブロックがいくつかある可能性があります。 –

0

あなたはこのような何かを行うことができます。

更新:操作はuiの仕事をします。つまり、uiスレッドでキューに入れる必要があります。どのUIフレームワークを使用しているのかは言わないが、そのすべてにその方法がある。例えば

あなたはdispatcher

+0

しかし、DoSomeLightweightOperation()はメインスレッド内で行う必要があります。これはUIを扱うものなので、UIスレッドで行う必要があります。 – Player

関連する問題