C# 中异步委托的 VB.NET 等价物是什么?

What's the VB.NET equivalent of async delegate in C#?

我正在尝试将以下扩展方法 (source) 从 C# 转换为 VB:

public static Task ForEachAsync<T>(this IEnumerable<T> source,
                                   int dop, Func<T, Task> body)
{
    return Task.WhenAll(
        from partition in Partitioner.Create(source).GetPartitions(dop)
        select Task.Run(async delegate {
            using (partition)
                while (partition.MoveNext())
                    await body(partition.Current);
        }));
}

delegate 的常规等价物是 Sub(),AFAIK,但我没想到它能在这种情况下工作,因为 Async 关键字(而且它没有).所以,我尝试使用 Function() 代替:

<System.Runtime.CompilerServices.Extension>
Public Function ForEachAsync(Of T)(source As IEnumerable(Of T),
                                   dop As Integer, body As Func(Of T, Task)) As Task
    Return Task.WhenAll(
        From partition In Partitioner.Create(source).GetPartitions(dop)
        Select Task.Run(Async Function() 'As Task '<-- see below.
                            Using partition
                                Do While partition.MoveNext()
                                    Await body(partition.Current)
                                Loop
                            End Using
                        End Function))
End Function

但这仍然无法编译并显示以下错误:

我做错了什么?在 VB 中执行此操作的正确方法是什么?

不是问题的真正答案,但是,如果它是真正的异步代码,则不需要对执行进行分区:

<System.Runtime.CompilerServices.Extension>
Public Function ForEachAsync(Of T)(
    source As IEnumerable(Of T),
    body As Func(Of T, Task)) As Task
    Return Task.WhenAll(        
        From item In source
        Select body(item))
End Function

在 C# 中,异步 Lambda 可以用 delegate type or using the invocation operator () followed by the => 标记表示为 lambda 运算符以调用匿名方法:

Task.Run(async ()=> { } );
Task.Run(async delegate { } );

在 VB.Net 中,匿名方法可以通过使用 Sub()Function() 的 Lambda 表达式调用,内联和 Sub / End Sub, Function() / End Function 块:

Task.Run(Async Sub() [operation on captured variables])
Task.Run(Sub()
             [operation on captured variables]
         End Sub))

Task.Run(Async Function() [operation on captured variables])
Task.Run(Function()
             Return [operation on captured variables]
         End Function))

VB.Net 的 LINQ to SQL 不允许在 Select 子句中等待,因为:

Await may only be used in a query expression within the first collection expression of the initial From clause or within the collection expression of a Join clause

Stephen Toub 的 Async/Await FAQ 中引用了它。

Select Task.Run(Async Function() ... ) 尝试 return 一个 IEnumerable(Of TResult) 而不是 IEnumerable(Of Task).

Language-Integrated Query (LINQ) (Visual Basic) 中的更多内容。

相反,LINQ to Objects - 在没有其他中间提供者的情况下使用 IEnumerable/IEnumerable<T> 集合 - 确实允许 Select 方法上的 async/await 模式:

<Extension>
Public Function ForEachAsync(Of T)(source As IEnumerable(Of T), dop As Integer, body As Func(Of T, Task)) As Task
    Return Task.WhenAll(
        Partitioner.Create(source).GetPartitions(dop).
        Select(Function(p) (
                   Task.Run(Async Function()
                                Using p
                                    While p.MoveNext()
                                        Await body(p.Current)
                                    End While
                                End Using
                            End Function))))
End Function

LINQ to SQL 的 C# 版本允许它。
为什么,因为同样的规则也应该适用于 C# 实现?

The .NET Language Strategy:

C#:

We will keep growing C# to meet the evolving needs of developers and remain a state of the art programming language. We will innovate aggressively, while being very careful to stay within the spirit of the language.

VB.Net:

We will keep a focus on the cross-language tooling experience, recognizing that many VB developers also use C#. We will focus innovation on the core scenarios and domains where VB is popular.

因此,2010 年断言的 VB and C# Coevolution 发生了变化:C#VB.Net 功能更新已分离。因此,鉴于新的语言策略,VB.NetC# 不再 显示大致相等的采用率