Я нахожусь в процессе преобразования синхронного кода в асинхронный код. У меня есть приложение Windows Form на VB.net, которое показывает представление физических устройств, которые являются частью регистрационного поста, управляемого почтовым менеджером.
Таким образом, класс PostManager используется для управления объектами RegistrationPost. Эти регистрационные посты содержат несколько устройств, которые так или иначе должны быть связаны с Socket коммуникацией. Эти устройства соответствуют интерфейсу IDevice путем реализации подпрограммы «connect».
Ниже приведена сокращенная версия кода, чтобы понять, что я пытаюсь сделать:
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, создается конечный автомат, так что, вероятно, нет необходимости идти до конца?
Было бы также лучше отказаться от 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