【发布时间】:2017-11-30 15:28:13
【问题描述】:
我正在尝试创建一个在其他两个系统的数据之间同步的系统。
我使用 VB 处理 ASP.NET Web 表单(无法更改)
主要的系统功能将采用 Web API 的形式,由计划任务或其他事件触发,例如网站表单或登录页面。
这些函数中的每一个都会调用 System 1 的 REST API 和 System 2 的 REST API,对数据进行操作,然后调用各个系统的 REST API 来更新双方。
我选择使用 ASP.NET Web Api 2 作为主系统,使用 HttpClient 调用函数。
每天将有数十万笔交易。很多!所以我选择对 HttpClient 使用 async/await 方法,(因为有很多同时处理的长请求),但是 ASP.NET 似乎迫使我将所有功能从下到上转换,包括 Web Api 函数和数据库访问异步!
所以我最终将所有函数更改为 Async,并且在所有调用它们的函数中我都使用 Await。
似乎一切正常。我不知道我所做的是否正确,而且我发现无法检查我的函数是否真的异步工作。
关于ConfigureAwait(False) 我添加它是因为我没有与上下文相关的操作。如果有,我将删除此声明。我读过建议在可能的情况下使用它。 (我说的对吗?)
小评论: 为什么我的解决方案很好???我试图通过创建更多的工作线程来避免阻塞主线程。为什么这是一个更好的解决方案?我正在创建很多等待,每个等待都启动一个工人。是不是比同步方案更糟糕的做法????
谁能告诉我我正在做的事情是否正确 - 请解释原因或是否有其他方法可以解决这种情况?
这里是示例代码(仅相关部分)。对您所看到的内容进行一点解释:
- WebApi 控制器具有登录功能
- Login 函数异步调用 System1.DoSomething
- System1.DoSomething 调用私有函数 System1.SetCredentials 异步
- System1.DoSomething 也使用 HttpHandler 来获取数据 来自 System1 的 API 的异步
- System1.SetCredentials 函数异步调用 MyLoginManager.GetCredentials
- MyLoginManager.GetCredentials 使用 DBHelper.ExecuteReaderAsync 异步调用数据库
- DBHelper.ExecuteReaderAsync 函数调用 ExecuteReaderAsync 异步地并且还使用异步地打开连接 OpenAsync() 函数
WebAPI 控制器
Public Class WebApiController
Inherits ApiController
Public Async Function Login() As Threading.Tasks.Task(Of IHttpActionResult)
Dim result As MyResult= Await System1.DoSomething().ConfigureAwait(False)
End Function
System1 类
Public Class System1
Public Shared Async Function DoSomething() As Task(Of MyResult)
Try
Using client As New HttpClient
client.BaseAddress = New Uri("blablabla")
Await SetCredentials(client).ConfigureAwait(False)
Dim response As HttpResponseMessage = Await client.GetAsync(urlParameters).ConfigureAwait(False)
... More code
End Using
Catch ex As Exception
End Try
End Function
Private Shared Async Function SetCredentials(client As HttpClient) As Task
Dim auth As BasicAuthenticationData = Await MyLoginManager.GetCredentials.ConfigureAwait(False)
Dim credentials As String = Cryptography.EncodeBase64(String.Format("{0}\{1}:{2}", auth.userName, auth.userPassword))
client.DefaultRequestHeaders.Add("Authorization", "Basic " & credentials)
... More code
End Function
End Class
MyLoginManager 类
Public Class MyLoginManager
Public Shared Async Function GetCredentials() As Threading.Tasks.Task(Of BasicAuthenticationData)
Dim auth As New BasicAuthenticationData
Dim dbConn As String = DBConnection.GetConnection(True)
Dim q As String = "SELECT * FROM BlaBlaBla"
Using sdr As SqlDataReader = Await DBHelper.ExecuteReaderAsync(dbConn, q, Nothing).ConfigureAwait(False)
... More code
End Using
Return auth
End Function
End Class
DBHelper 类
Public Class DBHelper
Public Shared Async Function ExecuteReaderAsync(ByVal dbConnection As String, ByVal commandText As String, ByVal params() As SqlParameter) As Threading.Tasks.Task(Of SqlDataReader)
Dim dbConnectionAsync As String = New SqlConnectionStringBuilder(dbConnection) With {
.AsynchronousProcessing = True
}.ToString
Dim objConn As New SqlConnection(dbConnectionAsync)
Dim oc As New SqlCommand(commandText, objConn)
Dim sdr As SqlDataReader
' Throws a custom exception if there is a problem
Try
Await oc.Connection.OpenAsync.ConfigureAwait(False)
sdr = Await oc.ExecuteReaderAsync(CommandBehavior.CloseConnection).ConfigureAwait(False)
Return sdr
Catch ex As Exception
End Try
End Function
End Class
【问题讨论】:
标签: asp.net vb.net asynchronous asp.net-web-api async-await