简体   繁体   English

连续链接任务,然后运行并行任务

[英]Chaining tasks with continuation and run parallel task afterward

The work flow of the parallel tasks 并行任务的工作流程

http://i.stack.imgur.com/luRnu.png

I am hoping to get help on the problem I am facing. 我希望能在遇到的问题上获得帮助。 So the problem is that I am running parallel tasks to search through folders for files. 因此,问题在于我正在运行并行任务以在文件夹中搜索文件。 Each task entails identifying files and add it to a array of files. 每个任务都需要标识文件并将其添加到文件数组中。 Next, wait until every task completes so that files are gathered up, then perform sorting on the results. 接下来,等待每个任务完成,以便收集文件,然后对结果进行排序。 Next, process the sorted file independently, by running one task per file to read through it to get a matching pattern back. 接下来,通过对每个文件运行一个任务以读取该文件来获取匹配的模式,从而独立处理已排序的文件。 The final stage is to aggregate all the results together in human readable format and display it in a user-friendly way. 最后阶段是将所有结果汇总为易于阅读的格式,并以用户友好的方式进行显示。

So the question is that I want to chain the tasks in a proper way that does not blocks the UI thread. 所以问题是我想以一种不会阻塞UI线程的适当方式链接任务。 I would like to be able to cancel everything at any stage the program is at. 我希望能够在程序处于任何阶段的情况下取消所有操作。

To sum it up: 把它们加起来:

Stage 1: Find files by searching through folders. 阶段1:通过搜索文件夹来查找文件。 Each task search recursively through a folder tree. 每个任务通过文件夹树进行递归搜索。

Stage 2: Sort all the files found and clean up duplicates 阶段2:对找到的所有文件进行排序并清理重复项

Stage 3: Start new tasks to process the files independently. 阶段3:启动新任务以独立处理文件。 Each task opens a file and search for matching pattern. 每个任务都会打开一个文件并搜索匹配的模式。

Stage 4: Aggregate result from every single file search into one giant result set and make it pretty for human to read. 第4阶段:将每次单个文件搜索的结果汇总到一个庞大的结果集中,使其易于阅读。

     List<Task> myTasks = new List<Task>();

// ==== stage 1 ======
        for(int i = 0; i < 10; i++) {
           string directoryName = directories[i];

           Task t = new Task(() =>
           {
              FindFiles(directoryName);
           });

           myTasks.Add(t);
            t.Start();
        }

// ==== stage 2 ====
        Task sortTask = Task.Factory.ContinueWhenAll(myTasks.ToArray(), (t) =>
        {
           if(_fileResults.Count > 1) {
              // sort the files and remove any duplicates
           }
        });

        sortTask.Wait();

// ==== stage 3 ====
        Task tt = new Task(() =>
        {
             Parallel.For(0, _fileResults.Count, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = token, TaskScheduler = _taskScheduler },
                    (i, loopstate) => {
              // 1. open file
              // 2. read file
              // 3. read file line by line
              }
        }

// == stage 4 === 
        tt.ContinueWith((t) =>
        {
           // 1. aggregate the file results into one giant result set
           // 2. display the giant result set in human readable format
        }, token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext());

      tt.start();

Don't synchronously wait for any of the tasks to finish. 不要同步等待任何任务完成。 If any of those operations need to take place after a previously created task, add that work as a continuation of that task instead. 如果在先前创建的任务之后需要执行任何这些操作,请添加该工作作为该任务的延续。

Have you considered using the async/await feature - By the sounds of your question, it's the perfect match for your needs. 您是否考虑过使用async/await功能-根据您的问题,它完全满足您的需求。 Here's a quick attempt at your problem using it: 这是使用它的快速尝试:

try
{
    List<Task<File[]>> stage1Tasks = new List<Task<File[]>>();

    // ==== stage 1 ======
    for (int i = 0; i < 10; i++)
    {
        string directoryName = directories[i];

        Task<File[]> t = Task.Run(() =>
        {
            return FindFiles(directoryName);
        },
            token);

        stage1Tasks.Add(t);
    }

    File[][] files = await Task.WhenAll(stage1Tasks).ConfigureAwait(false);

    // Flatten files.
    File[] _fileResults = files.SelectMany(x => x).ToArray();

    // ==== stage 2 ====
    Task<File[]> sortFilesTask = Task.Run(() =>
    {
        if (_fileResults.Count > 1)
        {
            // sort the files and remove any duplicates
            return _fileResults.Reverse().ToArray();
        }
    },
        token);

    File[] _sortedFileResults = await sortFilesTask.ConfigureAwait(false);

    // ==== stage 3 ====
    Task<SomeResult[]> tt = Task.Run(() =>
    {
        SomeResult[] results = new SomeResult[_sortedFileResults.Length];
        Parallel.ForEach(_sortedFileResults,
            new ParallelOptions {
                MaxDegreeOfParallelism = Environment.ProcessorCount,
                CancellationToken = token,
                TaskScheduler = _taskScheduler
            },
            (i, loopstate) =>
            {
                // 1. open file
                // 2. read file
                // 3. read file line by line
                results[i] = new SomeResult( /* here goes your results for each file */);
            });
        return results;
    },
        token);

    SomeResult[] theResults = await tt.ConfigureAwait(false);


    // == stage 4 === 
    // 1. aggregate the file results into one giant result set
    // 2. display the giant result set in human readable format
    // ....

}
catch (TaskCanceledException)
{
    // some task has been cancelled...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM