我提取了你的基本示例代码并对其进行了充实,直到它产生了结果:
async Task Main()
{
string[] a0_source = new[] { "Hello", "World" };
string[] a1_source = new[] { "Hi", "There" };
Task<string[]> A0 = ExecuteA(a0_source);
Task<string[]> A1 = ExecuteA(a1_source);
var results = await Task.WhenAll(A0, A1);
var output = String.Join(", ", results.SelectMany(x => x));
Console.WriteLine(output);
}
private static async Task<string[]> ExecuteA(string[] A)
{
var BCs = A.Select(r => ExecuteBC(r));
return await Task.WhenAll(BCs);
}
private static async Task<string> ExecuteBC(string value)
{
var result = await ExecuteB(value);
return await ExecuteC(result);
}
private static async Task<string> ExecuteC(string value)
{
return await Task.Run(() => value + "!C");
}
private static async Task<string> ExecuteB(string value)
{
return await Task.Run(() => value + "!B");
}
这会在控制台上生成Hello!B!C, World!B!C, Hi!B!C, There!B!C。
然后我介绍了微软的反应式框架(NuGet“System.Reactive”)并产生了这个中间结果:
async Task Main()
{
string[] a0_source = new[] { "Hello", "World" };
string[] a1_source = new[] { "Hi", "There" };
IObservable<string> query =
from a in a0_source.Concat(a1_source).ToObservable()
from b in Observable.FromAsync(() => ExecuteB(a))
from c in Observable.FromAsync(() => ExecuteC(b))
select c;
var output = String.Join(", ", await query.ToArray());
Console.WriteLine(output);
}
private static async Task<string> ExecuteC(string value)
{
return await Task.Run(() => value + "!C");
}
private static async Task<string> ExecuteB(string value)
{
return await Task.Run(() => value + "!B");
}
然后你可以更进一步,这样做:
async Task Main()
{
string[] a0_source = new[] { "Hello", "World" };
string[] a1_source = new[] { "Hi", "There" };
IObservable<string> query =
from a in a0_source.Concat(a1_source).ToObservable()
from b in Observable.Start(() => a + "!B")
from c in Observable.Start(() => b + "!C")
select c;
var output = String.Join(", ", await query.ToArray());
Console.WriteLine(output);
}
现在看起来相当优雅。最好的一点是,您可以通过简单的 .ToTask() 调用轻松地将 observable 转换为任务。 Observables 也是可等待的。这是一个简单的替换,更优雅。最好的是它也使用 LINQ 语法。如果您需要更多解释,请告诉我。