3

n関数で同時スレッドを開い ています:

List<string> _files = new List<string>();

public void Start()
{
    CancellationTokenSource _tokenSource = new CancellationTokenSource();
    var token = _tokenSource.Token;

    Task.Factory.StartNew(() =>
    {
        try
        {
            Parallel.ForEach(_files,
                new ParallelOptions
                {
                    MaxDegreeOfParallelism = 5 //limit number of parallel threads 
                },
                file =>
                {
                    if (token.IsCancellationRequested)
                        return;
                    //do work...
                });
        }
        catch (Exception)
        { }

    }, _tokenSource.Token).ContinueWith(
        t =>
        {
            //finish...
        }
    , TaskScheduler.FromCurrentSynchronizationContext() //to ContinueWith (update UI) from UI thread
    );
        }

スレッドが開いた後、リストからランダムなファイルが選択されることに気付きました。nリストから最初の要素を毎回選択することは可能ですか?

4

3 に答える 3

4

必要な動作を得るには、カスタムパーティショナーを作成する必要があります。「ランダム」に見える理由は、現在、ファイルリストをブロック単位でバッチ処理しているため、ソースリストが

List<string> files = List<string> { "a", "b", "c", "d", "e", "f", "g", "h", "i" };

分割すると、次のように均等に分割される場合があります (最大が 3 スレッドの場合)。

  • スレッド 1 の作業リスト: "a"、"b"、"c"
  • スレッド 2 の作業リスト: "d"、"e"、"f"
  • スレッド 3 の作業リスト: "g"、"h"、"i"

したがって、処理中のファイルを見ると、次のように見える場合があります

"a", "d", "g", "e", "b", "h", "c", "f", "i"

カスタム パーティショナーを作成すると、ワーク リストを次のようにするために、一度にバッチではなく、一度に 1 つのアイテムを取ることができます。

  • スレッド 1 の作業リスト: "a",GetTheNextUnprocessedString()
  • Thread2 の作業リスト: "b",GetTheNextUnprocessedString()
  • Thread3 の作業リスト: "c",GetTheNextUnprocessedString()

.NET 4.5 を使用している場合は、このファクトリを次のように使用できます。

Parallel.ForEach(Partitioner.Create(_files, EnumerablePartitionerOptions.NoBuffering),
                new ParallelOptions
                {
                    MaxDegreeOfParallelism = 5 //limit number of parallel threads 
                },
                (file, loopstate, index) =>
                {
                    if (token.IsCancellationRequested)
                        return;
                    //do work...
                });

.NET 4.5 を使用していない場合、これは簡単な作業ではないため、ここでは説明しません。上部にリンクした MSDN の記事を読むと、最終的には理解できるようになります。

私がすべきことは、「ファイルを順番に処理する必要が本当にあるのか?」と自問することです。それらを順番に並べる必要がない場合は、順序を強制することでおそらくプロセスが遅くなる可能性があるため、独自の順序付けを行います。

于 2013-10-31T14:45:04.840 に答える
0

もちろん、ファイルはランダムに選択されます。それが parallel.foreach の要点です。並列処理を行う場合、指定した 5 つのスレッドは、データ パーティショナーによって決定されたとおりに入力を使用します。

ただし、どうしても順序を維持したい場合は、parallel.foreach に指定できる OrderablePartitioner を確認してください。-> http://msdn.microsoft.com/en-us/library/dd989583.aspx もちろん、これによりパフォーマンスが低下しますが、スレッド用にパーティションを作成する方法を指定できます。

于 2013-10-31T14:39:42.910 に答える