并行任务的工作流程
我希望能够帮助解决我面临的问题。所以问题是我正在运行并行任务来搜索文件夹中的文件。每个任务都需要识别文件并将其添加到文件数组中。接下来,等待每个任务完成,以便收集文件,然后对结果执行排序。接下来,通过为每个文件运行一个任务来单独处理已排序的文件,以便读取它以获得匹配的模式。最后阶段是将所有结果以人类可读的格式汇总在一起,并以用户友好的方式显示。
所以问题是我想以一种不阻塞UI线程的正确方式链接任务。我希望能够在该计划的任何阶段取消所有内容。
总结一下:
第1阶段:通过搜索文件夹来查找文件。每个任务以递归方式搜索文件夹树。
第2阶段:对找到的所有文件进行排序并清理重复文件
阶段3:启动新任务以独立处理文件。每个任务都会打开一个文件并搜索匹配的模式。
阶段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();
答案 0 :(得分:1)
不要同步等待任何任务完成。如果需要在先前创建的任务之后执行任何操作,请将该工作添加为该任务的延续。
答案 1 :(得分:0)
您是否考虑过使用async/await
功能 - 根据您的问题的声音,它可以满足您的需求。以下是您使用它的问题的快速尝试:
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...
}