Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将任务与延续链接,然后运行并行任务_C#_Concurrency_Parallel Processing_Task Parallel Library_Cancellationtokensource - Fatal编程技术网

C# 将任务与延续链接,然后运行并行任务

C# 将任务与延续链接,然后运行并行任务,c#,concurrency,parallel-processing,task-parallel-library,cancellationtokensource,C#,Concurrency,Parallel Processing,Task Parallel Library,Cancellationtokensource,并行任务的工作流程 我希望在我面临的问题上得到帮助。所以问题是我正在运行并行任务来搜索文件夹中的文件。每个任务都需要识别文件并将其添加到文件数组中。接下来,等待每个任务完成,以便收集文件,然后对结果进行排序。接下来,独立地处理排序后的文件,通过对每个文件运行一个任务来读取它,以获得匹配的模式。最后一个阶段是以人类可读的格式将所有结果聚合在一起,并以用户友好的方式显示 所以问题是,我希望以一种不会阻塞UI线程的适当方式链接任务。我希望能够在计划的任何阶段取消所有内容。 总而言之: 阶段1:通过搜

并行任务的工作流程

我希望在我面临的问题上得到帮助。所以问题是我正在运行并行任务来搜索文件夹中的文件。每个任务都需要识别文件并将其添加到文件数组中。接下来,等待每个任务完成,以便收集文件,然后对结果进行排序。接下来,独立地处理排序后的文件,通过对每个文件运行一个任务来读取它,以获得匹配的模式。最后一个阶段是以人类可读的格式将所有结果聚合在一起,并以用户友好的方式显示

所以问题是,我希望以一种不会阻塞UI线程的适当方式链接任务。我希望能够在计划的任何阶段取消所有内容。

总而言之:

阶段1:通过搜索文件夹查找文件。每个任务通过文件夹树进行递归搜索

阶段2:对找到的所有文件进行排序并清除重复文件

阶段3:启动新任务以独立处理文件。每个任务打开一个文件并搜索匹配的模式

第四阶段:将每个文件搜索的结果聚合成一个巨大的结果集,并使其美观易读

     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();
List myTasks=new List();
//==第一阶段======
对于(int i=0;i<10;i++){
字符串directoryName=目录[i];
任务t=新任务(()=>
{
FindFile(目录名);
});
添加(t);
t、 Start();
}
//==第二阶段====
Task sortTask=Task.Factory.continuewhall(myTasks.ToArray(),(t)=>
{
如果(_fileResults.Count>1){
//对文件进行排序并删除任何重复项
}
});
sortTask.Wait();
//==第三阶段====
任务tt=新任务(()=>
{
Parallel.For(0,_fileResults.Count,new ParallelOptions{maxdegreeofpparallelism=Environment.ProcessorCount,CancellationToken=token,TaskScheduler=_TaskScheduler},
(i,循环状态)=>{
//1.打开文件
//2.读取文件
//3.逐行读取文件
}
}
//==第4阶段===
tt.ContinueWith((t)=>
{
//1.将文件结果聚合为一个巨大的结果集
//2.以人类可读的格式显示巨大的结果集
},标记,TaskContinuationOptions.OnlyOnRanToCompletion,TaskScheduler.FromCurrentSynchronizationContext());
tt.start();

不要同步等待任何任务完成。如果这些操作需要在先前创建的任务之后进行,请将这些工作添加为该任务的继续。

您是否考虑过使用
异步/wait
功能?从您的问题听起来,它非常适合您的需要。以下是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...
}
试试看
{
List STAGE1任务=新列表();
//==第一阶段======
对于(int i=0;i<10;i++)
{
字符串directoryName=目录[i];
Task t=Task.Run(()=>
{
返回FindFile(目录名);
},
代币);
阶段1任务。添加(t);
}
File[][]files=await Task.WhenAll(stage1Tasks.ConfigureAwait(false);
//展平文件。
File[]\u fileResults=files.SelectMany(x=>x).ToArray();
//==第二阶段====
Task sortFilesTask=Task.Run(()=>
{
如果(_fileResults.Count>1)
{
//对文件进行排序并删除任何重复项
返回_fileResults.Reverse().ToArray();
}
},
代币);
文件[]\u sortedFileResults=await sortFilesTask.ConfigureAwait(false);
//==第三阶段====
Task tt=Task.Run(()=>
{
SomeResult[]results=新的SomeResult[_sortedFileResults.Length];
并行。ForEach(_sortedFileResults,
新的并行选项{
MaxDegreeOfParallelism=Environment.ProcessorCount,
CancellationToken=令牌,
TaskScheduler=\u TaskScheduler
},
(i,循环状态)=>
{
//1.打开文件
//2.读取文件
//3.逐行读取文件
results[i]=newsomeresult(/*这里是每个文件的结果*/);
});
返回结果;
},
代币);
SomeResult[]theResults=await tt.ConfigureAwait(false);
//==第4阶段===
//1.将文件结果聚合为一个巨大的结果集
//2.以人类可读的格式显示巨大的结果集
// ....
}
捕获(TaskCanceledException)
{
//某些任务已被取消。。。
}

您不应该使用
任务
构造函数。如果要创建表示执行委托的任务,请使用
任务。运行
来创建和启动这样的任务。您不应该让这些任务中的每一个都改变
列表
来添加它们的结果。
列表
不是线程安全的,因此这不一定是安全的工作。让每个任务返回其计算结果时产生的值,并继续通过
Task
API访问该结果。我使用lock和interlock对共享对象进行锁定。共享对象是结果集。在您发布的代码中不是。即使如此,您也不应该这样做。您应该让每个任务将其结果设置为其计算的值。它表示语义更好的是,它允许对代码进行模块化,并在隔离状态下进行有效的分析,而且它也会更快,因为您不会在每个任务之间引入完全不必要的依赖关系。我同意您的观点。一旦我弄清楚如何将任务链接在一起,我可能会相应地对其进行更改