合并 2 个奇数和偶数数组并使用 TASK 操作显示为自然数

Merge 2 arrays with Odd and Even numbers and display as Natural Numbers with TASK Operation

假设我们有 2 个异步方法

public async Task<int[]> GetOddNumbers() 
{
  return new int[] { 1, 3, 5, 7, 9 };
} 
public async Task<int[]> GetEvenNumbers()
{
  return new int[] { 2, 4, 6, 8, 10 }; 
}

我想将数组和显示合并为 1,2,3,4,5,6,7,8,9,10

我们如何通过 C# 中的 TAP(基于任务的异步模式)实现这一点? 请大家帮忙提宝贵意见

您当前的实现不需要任何异步代码。

我想这只是一个简化的示例,所以我将它们视为异步方法。

static async Task Main(string[] args)
{
    var odds = await GetOddNumbers();
    var evens = await GetEvenNumbers();
    var numbers = (odds).Zip(evens)
      .SelectMany(tuple => new [] { tuple.First, tuple.Second });

    Console.ReadLine();
}
  1. 我们检索两个集合。
  2. 我们将 odds 中的一个元素组合 (Zip) 到 evens 中的另一个元素。所以,我们最终会得到以下结构(元组数组):
[
  (1,2),
  (3,4),
  (5,6),
  (7,8),
  (9,10),
]
  1. 为了将其展平,我们需要调用 SelectMany。您可以通过 First 属性 访问左侧项目,通过 Second 属性.
    访问右侧项目 3.1) 如果你只调用 Select 而不是 SelectMany 那么你最终会得到一个数组数组。
[
  [1,2],
  [3,4],
  [5,6],
  [7,8],
  [9,10],
]

3.2) 但是使用 SelectMany 我们将数组的数组展平为一个简单的数组。

[
  1,2,3,4,5,6,7,8,9,10
]

更新:OP 添加了一项新要求(作为注释),即数据应 one-by-one 和异步检索。

为了满足这个我们需要使用IAsyncEnumerable<T>。这使我们能够在可用时一次提供一个数据。

提供商方

因此,我们必须 return 和 IAsyncEnumerable<int> 而不是 returning Task<int[]>GetOddNumbersGetEvenNumbers 可以这样重写:

public static async IAsyncEnumerable<int> GetOddNumbers()
{
    var odds = new int[] { 1, 3, 5, 7, 9 };
    foreach (var odd in odds)
    {
        await Task.Delay(1000); //Whatever async method call
        yield return odd;
    }
}
public static async IAsyncEnumerable<int> GetEvenNumbers()
{
    var evens = new int[] { 2, 4, 6, 8, 10 };
    foreach (var even in evens)
    {
        await Task.Delay(1000); //Whatever async method call
        yield return even;
    }
}

消费端

我们可以利用 C# 8 新的 await foreach 关键字。IAsyncEnumerable 没有 built-in Zip 函数,所以我们需要使用自定义的,像这样: async-enumerable-dotnet

有了这些,Main 方法将如下所示:

static async Task Main(string[] args)
{
    var toBeIterated = async_enumerable_dotnet.AsyncEnumerable.Zip(z => z, GetOddNumbers(), GetEvenNumbers());
    await foreach (int[] oddEvenPair in toBeIterated)
    {
        Console.WriteLine(oddEvenPair[0]);
        Console.WriteLine(oddEvenPair[1]);
    }

    Console.WriteLine("Finished");
    Console.ReadLine();
}

它将一次打印出一对数据,然后在下一对之间等待一秒钟。

{1 sec wait}
1
2
{1 sec wait}
3
4
{1 sec wait}
5
6
{1 sec wait}
7
8
{1 sec wait}
9
10
Finished