VB.NET用Parallel.ForEachAsync改写Async/Await函数的正确方法及报错解决
VB.NET中Parallel.ForEachAsync的正确异步实现
问题概述
你原本使用Task.WhenAll结合循环处理账户异步任务:
For Each account In _accounts Dim newtask = account.readBalancesAndOrderForEachAccount().ContinueWith(Sub() account.LogFinishTask("Geting Balances and Order", starttime)) LogEvents("balance and order account " + account.ExchangeStringName + " is being done by task " + newtask.Id.ToString + " " + newtask.ToString) tasklist.Add(newtask) Next Await Task.WhenAll(tasklist)
尝试改用Parallel.ForEachAsync重构时,ChatGPT提供的代码触发了编译错误:
Error BC36945: The 'Async' modifier can only be used on Subs, or on Functions that return Task or Task(Of T).
错误代码如下:
Await Parallel.ForEachAsync(_accounts, Async Function(account) Dim newTask = account.readBalancesAndOrderForEachAccount() LogEvents($"Starting task {newTask.Id} for account {account.ExchangeStringName}. Task details: {newTask}") tasklist.Add(newTask) Await newTask account.LogFinishTask("Getting Balances and Order", starttime) End Function)
错误原因
VB.NET的语法规则要求:标记Async的Function必须明确返回Task或Task(Of T)类型,否则编译器会默认推断返回Object,违反异步方法的类型约束,触发BC36945错误。此外,Parallel.ForEachAsync的委托参数默认包含一个CancellationToken(用于任务取消),需要在方法签名中声明。
正确实现代码
' 正确的Parallel.ForEachAsync实现 Await Parallel.ForEachAsync(_accounts, Async Function(account, cancellationToken) As Task ' 启动异步任务 Dim newTask = account.readBalancesAndOrderForEachAccount() ' 记录任务启动日志 LogEvents($"Starting task {newTask.Id} for account {account.ExchangeStringName}. Task details: {newTask}") ' 等待任务完成 Await newTask ' 执行任务完成后的日志记录 account.LogFinishTask("Getting Balances and Order", starttime) End Function)
关键说明
- 返回类型声明:必须显式指定
As Task,满足VB.NET对异步Function的类型要求。 - 取消令牌:签名中添加
cancellationToken参数(如果你的readBalancesAndOrderForEachAccount方法支持取消,可以将令牌传入该方法,实现任务取消功能)。 - 无需手动维护tasklist:
Parallel.ForEachAsync会自动管理所有并行任务的生命周期,无需再将任务添加到列表并调用Task.WhenAll。 - 逻辑对齐原代码:将原
ContinueWith中的日志逻辑直接放在Await newTask之后,保持业务逻辑一致且代码更易读。
内容的提问来源于stack exchange,提问作者user4951
相关产品推荐
相关产品推荐

