我正在尝试将以下扩展方法(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中执行此操作的正确方法是什么?
答案 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