.net - .NET Async/Await - 何时返回任务和何时等待
问题描述
我正在将同步代码转换为异步代码。我在 VB.net 中有一个 Windows 窗体应用程序,它显示了物理设备的表示,这些物理设备是由 postmanager 管理的registrationpost 的一部分。
所以 PostManager 类用于操作 RegistrationPost 对象。这些注册帖子包含多个需要以一种或另一种方式通过 Socket 通信连接的设备。这些设备通过实现“连接”子/功能来符合 IDevice 接口。
下面是代码的精简版本,以了解我正在尝试做什么:
Private Sub Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Try
...
Dim pm As New PostManager
pm.ConnectAndStartPosts
...
Catch ex As Exception
...
End Try
End Sub
然后在 PostManager 类中:
Friend Sub ConnectAndStartPosts()
' The global variable "Posts" is a List of RegistrationPost objects
Parallel.ForEach(Of RegistrationPost)(Posts, Sub(x) x.ConnectAndStartReading())
End Sub
然后在 RegistrationPost 类中:
Public Sub ConnectAndStartReading()
Parallel.ForEach(Of IDevice)(AllDevices, Sub(x)
x.Connect()
...
End Sub)
End Sub
然后在 IDevice 内:
Public Sub Connect() Implements IDevice.Connect
' socket is a global variable of the type Socket(SocketType.Stream, ProtocolType.Tcp)
socket.Connect(IP, Port)
... more code gets executed (if connected, log a message)
NotifyPropertyChanged("Connected")
End Sub
好的,这一切正常,但我当然想使用 async/await 来获得异步连接到外部套接字的所有好处。但是我无法理解 async/await 关键字“冒泡”的程度?我害怕遇到性能问题,因为每次使用 async/await 关键字时,都会创建一个状态机,所以可能不需要一直向上?
放弃 Parallel.Foreach 并选择常规的 ForEach 会更好吗?甚至另一种方法?请参阅下面这将如何影响代码示例:
' Async/await here as well?
Private async Sub Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Try
...
Dim pm As New PostManager
await pm.ConnectAndStartPosts
...
Catch ex As Exception
...
End Try
End Sub
然后在 PostManager 类中:
' Leave this a regular 'Sub' or transform to async Function as Task?
Friend Sub ConnectAndStartPosts()
' The global variable "Posts" is a List of RegistrationPost objects
Parallel.ForEach(Of RegistrationPost)(Posts, async Sub(x) await x.ConnectAndStartReading())
End Sub
然后在 RegistrationPost 类中:
' Leave this a regular 'Sub' or transform to async Function as Task?
Public async Function ConnectAndStartReading() as Task
Parallel.ForEach(Of IDevice)(AllDevices, async Sub(x)
await x.Connect()
... more code, start reading, etc...
End Sub)
End Function
然后在 IDevice 内:
Public async Function Connect() as Task Implements IDevice.Connect
' socket is a global variable of the type Socket(SocketType.Stream, ProtocolType.Tcp)
await socket.ConnectAsync(IP, Port)
... more code gets executed (if connected, log a message)
NotifyPropertyChanged("Connected")
End Function
解决方案
我无法理解将 async/await 关键字“冒泡”多远?我害怕遇到性能问题,因为每次使用 async/await 关键字时,都会创建一个状态机,所以可能不需要一直向上?
你应该async
一路走下去。async
/的开销await
虽然不是零,但一旦您进行真正的 I/O,就会完全消失在噪音中。
放弃 Parallel.Foreach 并选择常规的 ForEach 会更好吗?甚至另一种方法?
是的。Parallel
适用于受 CPU 限制的代码。对于异步并发,使用Task.WhenAll
. 即,ConnectAsync
为每个设备调用您的新方法(例如,使用 LINQ Select
),然后Await Task.WhenAll
对生成的任务执行一次。您可以对注册帖子执行相同的操作。
推荐阅读
- django - django 中的 {% url %} 是什么?
- java - Android Facebook 登录弹出对话框
- android - 构建android源代码后如何刷到设备?
- vector - SymPy 中的向量积求和
- html - 为什么 Chrome 会报告我的代码中没有的 element.style 规则?
- python - 为什么我不能在此代码中将“elif”的条件放在“if”条件的同一行中?
- c# - 我正在运行一个 task.delay 异步函数,但是当我关闭表单并再次打开它时它仍然有效吗?
- javascript - 无法将事件侦听器添加到 HTML 元素
- html - @ViewChild 在使用 Angular 表单时返回 undefined
- python - 为什么除了jnius我不能导入pyjnius的任何东西?