0

Parallel .net 4についてよく読んでいますが、いつ使用するか少し混乱していると言わざるを得ません。

これは私の一般的なシナリオであり、多くのxmlファイルをデータベースに移行するタスクが与えられています。

私は通常私がしなければならない

  1. Xmlファイル(100.000)などを読み取り、番号順に並べます(各ファイルの名前は1.xml、2.xmlなどです)。
  2. データベースに保存します。

上記は並列プログラミングの完璧な候補だと思いました。

概念的には、一度に多くのファイルを処理したいと思います。

私は現在これを行っています:

private ResultEventArgs  progressResults=new ResultEventArgs();

public void ExecuteInParallelTest()
{
    var sw=new Stopwatch();
    sw.Start();
    int index = 0;
    cancelToken = new CancellationTokenSource();
    var parOpts = new ParallelOptions();
    parOpts.CancellationToken = cancelToken.Token;
    parOpts.MaxDegreeOfParallelism = Environment.ProcessorCount;  //It this correct?

    FileInfo[] files = myDirectory.EnumerateFiles("*.xml").ToArray();//Is this faster?
    TotalFiles = files.Count();
    try
    {
        Task t1 = Task.Factory.StartNew(() =>
        {
            try
            {
                Parallel.ForEach(files, parOpts, (file, loopState) =>
                {

                    if (cancelToken.Token.IsCancellationRequested)
                    {
                        cancelToken.Token.ThrowIfCancellationRequested();
                    }

                    index = Interlocked.Increment(ref index);

                    ProcessFile(file,index);

                                progressResults.Status=InProgress                                   

                    OnItemProcessed(TotalFiles,index,etc..);
                });
            }
            catch (OperationCanceledException ex)
            {
                OnOperationCancelled(new progressResults
                    {
                        progressResults.Status=InProgress                               
                        progressResults.TotalCount = TotalFiles;
                        progressResults.FileProcessed= index;
                        //etc..                                  
                    });

            }

            //ContinueWith is used to sync the UI when task completed.
        }, cancelToken.Token).ContinueWith((result) => OnOperationCompleted(new ProcessResultEventArgs
            {
                        progressResults.Status=InProgress
                        progressResults.TotalCount = TotalFiles;
                        progressResults.FileProcessed= index;
                        //etc..
            }), new CancellationTokenSource().Token, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
    }
    catch (AggregateException ae)
    {
        //TODO:
    }
   }

私の質問:私は.net 4.0を使用していますが、これらのファイルの処理を高速化するための最良/より簡単な方法はParallelを使用しています。上記の疑似コードで十分ですか、それとも重要なもの、ロックなどが不足していますか?

最も重要な質問は次のとおりです。私には制御できないため、最適化できないため、「ProcessFile」を忘れる最適化の余地はありますか

ファイルをチャンクに分割する必要があります(例:1-1000-1001-2000-2001-3000)パフォーマンスが向上します(どのように行いますか)

上記のコードを改善する方法をよりよく理解するのに役立つ返信またはリンク/コードスニペットに感謝します。

4

2 に答える 2

0

応答がないのは、コードがひどく間違っているためです。AsParallel() は GetFiles() に対して何もしません。files.Count() は実際に列挙可能なものを反復するため、ファイル (またはディレクトリのみ) を 2 回読み取るだけでなく、Count() を最初に実行してから、後でそれらを反復処理します。ディレクトリが変更された場合、ファイルを 2 回読み取り、一貫性のないカウントが生成される可能性があります。Task.Factory.StartNew を実行する必要があるようには見えません。これが唯一のタスク (内部で並列処理を生成する) であるためです。Parallel.ForEach は、すべての OperationCancelledException を単一の AggregateException にカプセル化しますが、すべての並列スレッドが作業を終了した後にのみカプセル化します。

于 2013-02-01T02:18:33.007 に答える
0

誰も適切な答えをくれなかったので、コードをそのまま残しました

于 2013-02-16T06:10:06.493 に答える