0

100K アイテムを含む並行コレクションがあります。コレクション内の各アイテムの処理には、最短で 100 ミリ秒、最長で 10 秒かかります。処理を並列化することで処理を高速化し、100 台のミニオンで同時に処理を実行したいと考えています。また、この処理が発生したときに、完了したパーセンテージだけでなく、特定のデータを UI に報告する必要もあります。

並列化されたサブタスクが、池に投げ込まれたパンを攻撃するミノーの群れのように、並行コレクションをかじりたいと思っています。並列化されたタスクに並行コレクションを公開するにはどうすればよいですか? 通常のループを作成して、ループ内で非同期タスクを起動し、それに IProgress を渡すことはできますか? これには並行コレクションも必要ですか?

Parallel.ForEach を使用することをお勧めしましたが、並列処理の度合いによって確立された各サブプロセスが、処理が完了した後だけでなく、処理する各アイテムと共にカスタム オブジェクトを UI に報告する方法がわかりません。100K アイテムのシェアを処理しています。

4

1 に答える 1

0

フレームワークは、この目的のためにIProgressインターフェースと、 Progressの実装を既に提供しています。進行状況を報告するには、progressvalue を指定してIProgress.Reportを呼び出します。値 T は、数値だけでなく、任意の型にすることができます。

各 IProgress 実装は独自の方法で機能します。Progress はイベントを発生させ、作成時に渡したコールバックを呼び出します。

さらに、Progress.Report は非同期で実行されます。内部では、 SychronizationContext.Postを使用して、Progress インスタンスを作成したスレッドでコールバックとすべてのイベント ハンドラーを実行します。

次のような進捗値クラスを作成すると仮定します。

class ProgressValue
{
    public long Step{get;set;}
    public string Message {get;set;}
}

次のように書くことができます。

IProgress<ProgressValue> myProgress=new Progress<ProgressValue>(p=>
{
    myProgressBar.Value=p.Step;
});

IList<int> myVeryLargeList=...;
Parallel.ForEach(myVeryLargeList,item,state,step=>
{
    //Do some heavy work
    myProgress.Report(new ProgressValue
    {
         Step=step,
         Message=String.Format("Processed step {0}",step);
    });
});

編集

おっとっと!Progress は IProgress を明示的に実装します。@Tim が気づいたように、 IProgress にキャストする必要があります。

myProgress を IProgress として明示的に宣言するようにコードを修正しました。

于 2013-08-02T11:06:40.973 に答える