服务(Windows服务)用于创建多个线程并执行每个线程负责的不同区域。对于两个特定线程,连接字符串和设置似乎被覆盖。这两个线程在某个时刻调用同一个类来执行需求。这两个线程都使用不同的数据库连接字符串,因此数据库托管在两个不同的区域。问题是,需要处理的记录是从正确的数据库中获取的,并且错误(由于不正确的设置)被返回并记录在不正确的数据库上。此问题是间歇性的,不会定期发生。正在处理的记录将因此问题而失败,但是当 1 分钟后运行同一记录时,一切都会成功(正确的数据库连接和设置)
类中发起的两个线程: 连接字符串位于通过 DBUtils 类检索的数据库中
Public Class MyClassName
Private WithEvents MyTimer As Timers.Timer = Nothing
Private eveHUBSPOTUPDATEEVENTS_NZ As New Threading.Thread(AddressOf EventHubSpotUpdateEvents)
Private eveSYSEVENTS_AUS As New Threading.Thread(AddressOf EventSystemEvents_Aus)
End Class
类的构造函数
Public Sub New()
InitializeComponent()
//other config settings
ServicePointManager.SecurityProtocol = Net.SecurityProtocolType.Tls12 Or Net.SecurityProtocolType.Tls11 Or Net.SecurityProtocolType.Tls Or Net.SecurityProtocolType.Ssl3
End Sub
启动事件
Protected Overrides Sub OnStart(ByVal args() As String)
SetTimerProps(False)
End Sub
Private Sub SetTimerProps(ByVal doDisable As Boolean)
ClearCounters()
If doDisable Then
If MyTimer IsNot Nothing Then
MyTimer.Enabled = False
MyTimer = Nothing
End If
Else
_mustDoHubspotEventsNZ = MustDOHubSpotEventsNZ()
_mustDoHubspotEvents_Aus = MustDoHubSpotEvents_Aus()
MyTimer = New Timers.Timer With {
.Interval = 10000, '10 Seconds
.AutoReset = False,
.Enabled = True
}
End If
结束子
然后在计时器上创建线程(与上面相同的类):
Private Sub MyTimer_Elapsed(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs) Handles MyTimer.Elapsed
Try
MyTimer.Enabled = False
IncrementCounters()
If Not eveHUBSPOTUPDATEEVENTS_NZ.IsAlive Then
eveHUBSPOTUPDATEEVENTS = New Threading.Thread(AddressOf EventHubSpotUpdateEvents) With {
.IsBackground = True,
.Priority = Threading.ThreadPriority.Normal
}
eveHUBSPOTUPDATEEVENTS_NZ.Start()
End If
If nSYSEVENTS_AUS_Counter > 1 AndAlso Not eveSYSEVENTS_AUS.IsAlive Then
nSYSEVENTS_AUS_Counter = 0
If _mustDoSystemEvents_Aus Then
eveSYSEVENTS_AUS = New Threading.Thread(AddressOf EventSystemEvents_Aus) With {
.IsBackground = True,
.Priority = Threading.ThreadPriority.Highest
}
eveSYSEVENTS_AUS.Start()
End If
End If
Catch ex As Exception
//Error Handling
MyTimer.Enabled = True
End Sub
这两个线程都会转到一个方法来检索需要处理的记录。
对于 NZ 进程,连接字符串
Public Class EventsNZ
Public Sub New()
_connectionString = DBUtils.SureSetting.GetSetting("ConnStringNZ")
_environment = DBUtils.SureSetting.GetSetting("Environment")
End Sub
End Class
对于 Aus 进程,连接字符串
Public Class EventsAus
Public Sub New()
_connectionString = DBUtils.SureSetting.GetSetting("ConnStringAus")
_environment = DBUtils.SureSetting.GetSetting("Environment")
End Sub
End Class
然后检索记录(新西兰):
Private Sub HandleEventsNZ()
Try
Const sqlEvents = "script to retrieve the required records"
Dim systemEventsData = _dbHelper.GetLongRunningSQLDataTable(sqlEvents, 600, Nothing)
For Each eventItem As DataRow In systemEventsData.Rows()
Dim feedback = HandleHubspotEvent(eventItem, _connectionString )
UpdateEventToCompleted(StringAsLong(eventItem("Sys_Key")), feedback)
Next
systemEventsData.Dispose()
Catch ex As Exception
//some error handling
End Try
End Sub
Private Function HandleHubspotEvent(eventData As DataRow, dbConnectionString As String) As String
Try
//some validations
Dim hubspotWorker As New HubspotIntegrator(_connectionString, productId, StringAsInteger(eventData("User_Cde")))
Return hubspotWorker.HubspotCreateOrUpdate(eventData("Area_Cde").ToString(),
StringAsLong(eventData("Reference_Cde")),
eventData("Other_Ref2").ToString(), eventResult)
Catch ex As Exception
//error handling
End Try
End Sub
End Function
然后检索记录(澳大利亚): 检索记录的过程类似。由于即将发生的移民,澳大利亚只能属于自己的类别。一旦Aus数据迁移到NZ端,这个类和对应的线程就会被移除。
Aus会达到这个方法:
Private Function HandleHubspotEvent(ByRef eventData As DataRow) As String
Try
//some validation
Dim hubspotWorker As New HubspotIntegrator(_connectionString, productId, StringAsInteger(eventData("Event_User_Cde")))
Return hubspotWorker.HubspotCreateOrUpdate(eventData("Event_Area_Cde").ToString(),
StringAsLong(eventData("Event_Reference_Cde")),
eventData("Event_Other_Ref2").ToString(), "")
Catch ex As Exception
//error handling
End Try
End Function
到目前为止,已使用正确的连接。 他们都到达同一个班级来处理这个过程。
调用 HubspotIntegrator 类时,连接是使用不可变属性设置的。连接在过程中的任何地方(或任何设置)都不会更改。连接字符串传递给此类。但由于某种原因,连接字符串最终在该过程中被更改。
Public Sub New(ByVal dbConnectionString As String, ByVal productId As Integer, ByVal userId As Integer)
If String.IsNullOrEmpty(dbConnectionString) OrElse dbConnectionString = "" Then
Throw New ArgumentException("Invalid Connection String!")
End If
If productId = 0 Then
Throw New ArgumentException("Invalid Product ID!")
End If
_dbConnectionString = dbConnectionString
_dbHelper = New DBUtil(_dbConnectionString)
_dbLookup = New SureDBLookup(dbConnectionString)
_sureQuote = New SureQuote(dbConnectionString)
_productId = productId
_systemMappingWorker = New SureSystemMapping(_dbConnectionString)
_userId = userId
_hsDataHelpers = New HubspotDataHelpers(dbConnectionString)
Dim productRuleData = _dbLookup.GetProductRuleData(productId, 0, "ALLOW_HUBSPOT", Nothing)
If productRuleData Is Nothing OrElse productRuleData("Pro_Val1").ToString <> "Y" Then
Throw New ArgumentException("Invalid Product ID! Not a HubSpot product")
End If
_hubspotBearerToken = DBUtils.SureSetting.GetSetting(productRuleData("Pro_Val2").ToString().Trim())
If _hubspotBearerToken = Nothing Then
Throw New ArgumentException("Invalid Hubspot BearerToken - HUBSPOT_BEARERTOKEN is not defined")
End If
结束子
任何关于为什么/如何发生这种情况的建议将不胜感激?如果有什么我遗漏的东西我可以看看(已经看了一周但仍然没有看到问题)
在我看来,检索连接字符串和环境的两个函数都设置相同的顶级变量 _connectionString 和 _environment。 由于它们在单独的线程中运行,因此看起来可能部分工作正常,但正如您所指出的,连接字符串会发生更改,因为两个函数调用之一正在覆盖它。
您的 HandleEventsNZ 子程序如何知道要使用哪个连接字符串?