Oli*_*yre 2 .net c# task-parallel-library
.Net 中是否有一种优雅的方法可以在多线程中执行命令图,其中每个命令只有在其所有父命令都被执行后才能执行?
例如,Visual Studio 在多线程编译解决方案时执行此类计算(每个项目在其所有依赖项都已编译后即可编译)。
另一个例子是,如果您想在不破坏关系约束的情况下逐表克隆(或加载)完整数据库,从顶级父表开始,然后执行子表。(假设至少存在一种表的拓扑排序)。
System.Threading.Tasks.Task 似乎使用“task.ContinueWith()”处理命令链的情况,但它似乎不会威胁命令图的情况。
尝试在任务流程开始时将任务与“Task.WaitAll(dependencies)”一起使用是可行的。但它效率不高,因为它开始启动第一个任务(可能会等待)而不是启动准备好的任务。这是我用来检查的代码:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
namespace ParallelProcessing
{
/// <summary>
/// There is the exemple Dependency graph:
///
/// MyTypedDataSet (long job) MyTools
/// ^ ^ ^ ^
/// |- Project 0 | | |- MyControls
/// ... | |
/// |- Project 99 |- MyForm ----|
///
///
/// 'MyControls' should compile quickly after MyTools. Instead of that, MyControls is flooded by Project 0..99
/// </summary>
public class TestTasks
{
public static void Trace(string message)
{
Console.WriteLine("[" + Task.CurrentId + "] " + message);
System.Diagnostics.Trace.WriteLine(DateTime.Now.ToString("mm:ss.fff") + " [" + Task.CurrentId + "] " + message);
}
private static void compile(string projectName, int duration, params Task[] dependency)
{
Task.WaitAll(dependency);
TestTasks.Trace("Start compiling " + projectName);
Thread.Sleep(duration);
TestTasks.Trace("End compiling " + projectName);
}
public static void RunTest()
{
Task taskMyTypedDataSet = new Task(() => TestTasks.compile("MyTypedDataSet", 10000));
taskMyTypedDataSet.Start();
Task taskMyTools = new Task(() => TestTasks.compile("MyTools", 2000));
taskMyTools.Start();
List<Task> lotOfOtherProjets = new List<Task>();
for (int i = 0; i < 100; i++)
{
string projectName = "Project" + i;
Task task = new Task(() => TestTasks.compile(projectName, 100, taskMyTypedDataSet));
task.Start();
lotOfOtherProjets.Add(task);
}
Task taskMyControls = new Task(() => TestTasks.compile("MyControls", 100, taskMyTools));
taskMyControls.Start();
Task taskMyForms = new Task(() => TestTasks.compile("MyForms", 100, taskMyControls, taskMyTypedDataSet));
taskMyForms.Start();
Task.WaitAll(taskMyTypedDataSet, taskMyForms);
Task.WaitAll(lotOfOtherProjets.ToArray());
TestTasks.Trace("Process done");
Console.ReadLine();
}
}
}
Run Code Online (Sandbox Code Playgroud)
您知道此类问题是否有一个巧妙的解决方案?
您可以用于TaskFactory.ContinueWhenAll()此用途。
例如:
var task1 = Task.Factory.StartNew(() => { /* some computation */ });
var task2 = Task.Factory.StartNew(() => { /* another computation */ });
var continuationTask = Task.Factory.ContinueWhenAll(
new[] { task1, task2 }, tasks => { /* dependent computation */ });
Run Code Online (Sandbox Code Playgroud)
在 .Net 4.5 中,Task.WhenAll()做了一些非常类似的事情。
| 归档时间: |
|
| 查看次数: |
3254 次 |
| 最近记录: |