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

时间:2019-05-06 04:26:40

标签: c# vb.net lambda async-await c#-to-vb.net

我正在尝试将以下扩展方法(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

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

  • WhenAll

    Overload resolution failed because no accessible 'WhenAll' can be called with these arguments:
        'Public Shared Overloads Function WhenAll(Of TResult)(tasks As IEnumerable(Of Task(Of TResult))) As Task(Of TResult())': Type parameter 'TResult' cannot be inferred.
        'Public Shared Overloads Function WhenAll(Of TResult)(ParamArray tasks As Task(Of TResult)()) As Task(Of TResult())': Type parameter 'TResult' cannot be inferred.
    
  • Await body(partition.Current)

      

    “等待”只能在第一个查询表达式中使用   初始'From'子句或在   “ Join”子句的集合表达式。

  • [警告],位于Async Function()(如果我添加As Task,它就消失了)

      

    函数'<anonymous method>'不会在所有代码上返回值   路径。当运行时,可能会在运行时发生空引用异常。   结果被使用。

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

2 个答案:

答案 0 :(得分:3)

在C#中,异步Lambda可以用delegate type表示,也可以使用调用运算符()和后跟=>标记作为lambda运算符来调用匿名方法:

DECLARE @version INT;
SET @version =
(
    SELECT TOP 1 CAST(Version AS INT)
FROM VersionTable
ORDER BY ID DESC

);

IF @version <= 1
    GOTO Version_A;

IF @version > 1
    GOTO Version_B;

Version_A:

UPDATE table
SET Column1 = 'A'
    Column2 = 'B'
WHERE Id = '123456'

Version_B:

UPDATE table
SET Column1 = 'A'
    Column2 = 'B'
    Column3 = 'C'
WHERE Id = '123456'

VB.Net使用匿名方法可以通过内联或多行Sub()或Function()与Lambda表达式一起调用:

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

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

  

等待只能在第一个查询表达式中使用   初始From子句或在   Join子句的集合表达式

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

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)) 尝试返回Select Task.Run(Async Function() ... )而不是IEnumerble(Of TResult)

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

相反,LINQ to Objects –在没有其他中间提供程序的情况下与IEnumerble(Of Task)集合一起使用–确实允许在IEnumerable/IEnumerable<T>方法上进行异步/等待模式:

Select

LINQ to SQL的C#版本允许它代替。
为什么,因为同一规则也应适用于C#实现?正在调查...

答案 1 :(得分:0)

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

<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