关于异步编程的建议... VB .NET

时间:2021-02-02 22:53:56

标签: .net vb.net multithreading asynchronous thread-safety

我有一个桌面应用程序,用户可以在其中选择表单中显示的多行(实际上是报关单)并通过 Web 服务发送它们以获取包含当前状态信息的响应,这些信息需要在数据库。

从现在开始,这个过程是同步进行的。获取第一行,使用 Web 服务,等待响应,更新数据库中的状态,然后移动到下一行。但是每次处理的行数在增加(一次 4000-5000),并且需要一段时间才能完成。

所以我所做的是或多或少像这样为每一行并行化 Web 服务的消耗:

'I can't parallelize the transactions with the database (business logic reasons), 
'so I use a queue for storing the responses as they arrive 
Private ResponseQueue as ConcurrentQueue(Of WebServiceResponseDataType)

Private NumberOfRowsToSend as Integer
Private CounterResponsesProcessed as Integer

Public Sub Send(ByVal dataTableRowsToSend As DataTable) 
  
    NumberOfRowsToSend = dataTableRowstoSend.Rows.Count()
    
    'I use a separate Thread to launch the method that will be updating the database 
    'as the queue is filled with responses
    Dim responseProcessorThread as Thread
    responseProcessorThread = New Thread(AddressOf ResponseProcessor)
    responseProcessorThread.Start()

    For Each row In dataTableRowsToSend.Rows
         Dim dataToSend() as Object
        'Do some previous validations and data formatting here.
        'I need to get some IDs from another tables in the database 
        'and increment them before consuming the web servcie. 
        'To avoid duplicate IDs I keep this part synchronous.
         
        'If the validations are passed I use the ThreadPool to queue the consumption of the WebService
         ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf WebServiceConsumption)), dataToSend)
    Next
 
    'Wait for all responses to be processed
    'PS. I'm controlling if there is an exception during the webservice consumption,
    'generating a fake response in that case so the user can see what went wrong
     responseProcessorThread.Join()

End Sub

Private Sub ResponseProcessor()
        Dim WebServiceResponse As WebServiceResponseDataType

        While CounterResponsesProcessed < NumberOfRowsToSend 
             If ResponseQueue.Count > 0 AndAlso ResponseQueue.TryDequeue(WebServiceResponse) Then
                 UpdateRowStateInDataBase(WebServiceResponse)
                 CounterResponsesProcessed += 1
             End If
        End While
End Sub

Private Sub WebServiceConsumption (ByVal dataToSend() as Object)
     'This function consumes the web service and waits for the response. 
     'When the response arrives it goes to the queue:
      ResponseQueue.Enqueue(responseData)
End Sub

使用此代码,过程要快得多,因为我不必等待前一行的响应从下一行开始。

但我不习惯并行编程,我不确定这是否是一种好方法,或者我是否做了一些被认为是不好的做法。

即我不舒服使用计数器来控制何时更新数据库中的所有响应以了解过程何时完成。同样在编写这段代码后,我一直在阅读我应该避免直接使用线程并使用任务来代替。

0 个答案:

没有答案