如何在 VB.NET 中编写异步子程序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45870469/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to write an Async Sub in VB.NET?
提问by Andrew
Public Class LoginManager
Implements ILoginManager
Private ReadOnly _iLoginRepository As ILoginRepository
Public Sub New()
_iLoginRepository = New LoginRepository()
End Sub
Public Async Sub InsertFailedLoginAttempt(failedLoginAttempt As FailedLogin) Implements ILoginManager.InsertFailedLoginAttempt
'Example of the S in Solid (Single Repsonsibilty)
'Need to call these method async. But await errors
_iLoginRepository.InsertFailedLoginAttemptAsync(failedLoginAttempt)
_iLoginRepository.InsertFailedLoginAttemptIntoLoginMasterAsync(failedLoginAttempt)
End Sub
End Class
Repsoitory Interface:
资源库接口:
Public Interface ILoginRepository
Function IsUserAuthenticatedAsync(ByVal cID As String, ByVal password As String, ByVal IsExternalUser As Boolean) As Task(Of Boolean)
Sub InsertFailedLoginAttemptAsync(ByVal failedLoginAttempt As FailedLogin)
Sub InsertFailedLoginAttemptIntoLoginMasterAsync(ByVal failedLoginAttempt As FailedLogin)
End Interface
Repository Implementation:
存储库实现:
Public Class LoginRepository
Implements ILoginRepository
Public ReadOnly _applicationDBContext As New ApplicationDBContext()
Public Async Sub InsertFailedLoginAttemptAsync(failedLoginAttempt As FailedLogin) Implements ILoginRepository.InsertFailedLoginAttemptAsync
Using _applicationDBContext
_applicationDBContext.RepFailedLogins.Add(failedLoginAttempt)
Await _applicationDBContext.SaveChangesAsync()
End Using
End Sub
Public Async Sub InsertFailedLoginAttemptIntoLoginMasterAsync(failedLoginAttempt As FailedLogin) Implements ILoginRepository.InsertFailedLoginAttemptIntoLoginMasterAsync
Using _applicationDBContext
_applicationDBContext.RepFailedLoginMasters.Add(failedLoginAttempt)
Await _applicationDBContext.SaveChangesAsync()
End Using
End Sub
''' <summary>
''' Determine whether a user is authenticated, be it an internal or external user
''' I have condensed two methods into one
''' </summary>
''' <param name="cID"></param>
''' <param name="password"></param>
''' <param name="IsExternalUser"></param>
''' <returns></returns>
Public Async Function IsUserAuthenticatedAsync(cID As String, password As String, IsExternalUser As Boolean) As Task(Of Boolean) Implements ILoginRepository.IsUserAuthenticatedAsync
If (IsExternalUser And String.IsNullOrEmpty(password)) Then
Throw New ArgumentNullException("External user requires password")
End If
Dim user As Chaser
Dim toRet As Boolean
Using _applicationDBContext
'Two ways to use LINQ
'First is LINQ Lambda sybntax(little harder to read)
user = Await _applicationDBContext.Chasers.Where(Function(x) x.CID = cID).FirstOrDefaultAsync()
'Second is LINQ Query syntax(looks more like SQL just more verbose
'user = From x In _applicationDBContext.Chasers
' Where x.CID = cID
' Select x
End Using
If IsNothing(user) Then
toRet = False
ElseIf Not IsExternalUser And Not IsNothing(user) Then
toRet = True
ElseIf IsExternalUser And user.Hash_Password = password Then
toRet = True
End If
Return toRet
End Function
End Class
I'm trying to call the InsertFailedLoginAttemptAsyncrepository method in my manager. It is an async method but I am unable to await the method. How can I make this method awaitable?
我正在尝试InsertFailedLoginAttemptAsync在我的经理中调用存储库方法。这是一个异步方法,但我无法等待该方法。我怎样才能让这个方法等待?
I believe it has something to do with the interface and not making it an async method like in C# but I'm unable to do this.
我相信它与接口有关,而不是像 C# 那样使它成为异步方法,但我无法做到这一点。
回答by Nkosi
Subs should not be async. Event handlers are the only exception to that rule. You await Taskwhich can only be returned from a Function. If the intention is to make that interface async then all the members need to be functions that return a Taskor its derivative.
Subs 不应该是异步的。事件处理程序是该规则的唯一例外。您 awaitTask只能从Function. 如果目的是使该接口异步,则所有成员都需要是返回 aTask或其派生类的函数。
Async is something that bubbles all the way through when used. That said the ILoginManageralong with the ILoginRepositoryshould be refactored (if possible) to follow the proper syntax.
异步是在使用时一直冒泡的东西。也就是说ILoginManager,ILoginRepository应该重构(如果可能)以遵循正确的语法。
Reference: Async/Await - Best Practices in Asynchronous Programming
回答by Andrew
Fixed via Nkosi's reply:
通过 Nkosi 的回复修复:
Interface:
界面:
Public Interface ILoginRepository
Function IsUserAuthenticatedAsync(ByVal cID As String, ByVal password As String, ByVal IsExternalUser As Boolean) As Task(Of Boolean)
Function InsertFailedLoginAttemptAsync(ByVal failedLoginAttempt As FailedLogin) As Task
Function InsertFailedLoginAttemptIntoLoginMasterAsync(ByVal failedLoginAttempt As FailedLogin) As Task
End Interface
Manager method:
管理员方法:
Public Async Function InsertFailedLoginAttempt(failedLoginAttempt As FailedLogin) As Task Implements ILoginManager.InsertFailedLoginAttempt
'Example of the S in Solid (Single Repsonsibilty)
Await _iLoginRepository.InsertFailedLoginAttemptAsync(failedLoginAttempt)
Await _iLoginRepository.InsertFailedLoginAttemptIntoLoginMasterAsync(failedLoginAttempt)
End Function

