如何在VB.NET中编写异步子程序?

6
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

仓库接口:

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

仓库实现:

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

我正在尝试在我的管理器中调用InsertFailedLoginAttemptAsync存储库方法。它是一个异步方法,但是我无法等待该方法。如何使此方法可等待?

我认为这与接口有关,不像在C#中将其作为异步方法,但我无法做到这一点。


1
Sub 不应该是异步的。事件处理程序是唯一的例外。您可以等待只能从 Function 返回的 Task。如果意图是使该接口异步,则所有成员都需要是返回 Task 或其派生类的函数。 - Nkosi
2个回答

11
Sub不应该是异步的。事件处理程序是唯一的例外。您需要等待只能从Function返回的Task。如果意图是使该接口异步,则所有成员都需要是返回Task或其派生类的函数。

使用时,异步是一种贯穿始终的东西。也就是说,ILoginManager以及ILoginRepository应该被重构(如果可能的话)以遵循正确的语法。

参考:Async/Await - 异步编程的最佳实践


2

通过Nkosi的回复已经解决:

接口:

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

管理器方法:

 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接