如何在C#中切换多个任务的异步/同步处理?
我希望能够在任务的并行和同步处理之间切换以进行测试/分析。
最初我有一个内联初始化的任务数组。虽然这对并行来说很好,但我发现我的同步代码不起作用,因为每个方法都会在数组初始化时激活。
我决定尝试Lazy。这段代码是否正确?如果没有,这是如何最好地实现的?
var runTasks = new Lazy<Task<ProcessWithResult>>[]
{
new Lazy<Task<ProcessWithResult>>(() => GetHeaderRecord()),
new Lazy<Task<ProcessWithResult>>(() => GetChildType1Entities()),
new Lazy<Task<ProcessWithResult>>(() => GetChildType2Entities()),
new Lazy<Task<ProcessWithResult>>(() => GetChildType3Entities()),
};
if (Settings.Default.AsyncProcessing)
{
Task.WaitAll(runTasks.Select(x => x.Value).ToArray());
}
else
{
// do these in sequence
runTasks.ToList().ForEach(t => t.Value.Wait());
}
// carryon...
每个GetX()方法签名都是这样的:
public async Task<ProcessWithResult> GetChildType1Entities()
在数据库或文件i / o上至少进行一次异步操作。
答案 0 :(得分:1)
你的方法可行,但我会避免使用Lazy。
C#中已经存在一个惰性语言构造,它的收益率会返回,并且会产生更清晰的代码:
public static class Runner
{
public static async Task<IEnumerable<ProcessWithResult>> RunAll(this IEnumerable<Task<ProcessWithResult>> tasks, bool runSequentially)
{
if (!runSequentially) return await Task.WhenAll(tasks);
var results = new List<ProcessWithResult>();
foreach (var task in tasks)
results.Add(await task);
return results;
}
}
public class Tests
{
[Test]
public void RunInParallel()
{
var results = GetAllTasks().RunAll(false).Result;
CollectionAssert.AreEqual(new[] { 2, 1 }, results.OrderBy(r => r.WhenFinished).Select(r => r.Id));
}
[Test]
public void RunInSequentially()
{
var results = GetAllTasks().RunAll(true).Result;
CollectionAssert.AreEqual(new[] { 1, 2 }, results.OrderBy(r => r.WhenFinished).Select(r => r.Id));
}
IEnumerable<Task<ProcessWithResult>> GetAllTasks()
{
yield return RunTask(1, 1000);
yield return RunTask(2, 100);
}
async Task<ProcessWithResult> RunTask(int id, int wait)
{
await Task.Delay(wait);
return new ProcessWithResult {Id = id, WhenFinished = DateTime.Now};
}
}
public class ProcessWithResult
{
public int Id { get; set; }
public DateTime WhenFinished { get; set; }
}
这种方法仍然在生产和测试中同步运行。