我正被迫在我正在开发的VBA工具中连接到某些.net服务。我使用一个函数来返回缓存的实例,或者如果尚未创建它,则创建一个新的实例。
如果对象出现任何问题(例如连接超时),下次我尝试使用它时,会收到错误
通信对象System.ServiceModel.Channels.ServiceChannel不能用于通信,因为它处于Faulted状态。
我已经看到这个错误在整个网络上弹出,但都是使用具有try-catch块的正确语言。
当缓存实例被使用并在“On Error Goto”语句中处理它时,我不想等待此错误发生,我想在检索缓存对象以供使用时防止它发生。我无法在任何地方找到这个东西的对象模型,只是在初始化对象上设置监视器。我可以在检索时使用什么属性或测试来确定对象是否处于故障状态?
Private Function GetMRLDIntegrationService() As Object
Const ServiceAddress = "service:mexAddress=""net.tcp://hydfwdvweb001/Integration/MrldIntegrationService.svc/Mex""," & _
"address=""net.tcp://hydfwdvweb001/Integration/MrldIntegrationService.svc/""," & _
"contract=""IMrldSimplexIntegration"", contractNamespace=""http://tempuri.org/""," & _
"binding=""SimplexIntegration"", bindingNamespace=""http://tempuri.org/"""
Static cachedInstance As Object
If Not cachedInstance Is Nothing Then
''//If *DETECT ERROR STATE HERE* Then Set cachedInstance = Nothing
End If
If cachedInstance Is Nothing Then Set cachedInstance = GetObject(ServiceAddress)
If cachedInstance Is Nothing Then Err.Raise 1, , _
"The MRLD server did not respond to the request to provide the service object."
Set GetMRLDIntegrationService = cachedInstance
End Function
在其他方法中,在另一种方法中,这就是错误发生的地方,而现在是优雅地处理错误为时已晚:
Private Sub FillFromRiskID(ByVal riskID As String)
...
Process_MRLD_Result GetMRLDIntegrationService().GetSerializedRisk(riskID, "1", uName, pWord)
...
End Sub
感谢您的帮助
答案 0 :(得分:0)
这是有效的解决方案,但我试图避免,因为它很丑陋,并且在大多数情况下浪费时间,而缓存对象没有任何问题。在某些情况下,GetSerializedRisk需要15秒才能返回,即使返回值是无效登录或错误请求ID。
Private Function GetMRLDIntegrationService() As Object
Const ServiceAddress = "service:mexAddress=""net.tcp://hydfwdvweb001/Integration/MrldIntegrationService.svc/Mex""," & _
"address=""net.tcp://hydfwdvweb001/Integration/MrldIntegrationService.svc/""," & _
"contract=""IMrldSimplexIntegration"", contractNamespace=""http://tempuri.org/""," & _
"binding=""SimplexIntegration"", bindingNamespace=""http://tempuri.org/"""
Static cachedInstance As Object
If Not cachedInstance Is Nothing Then
''If *DETECT ERROR STATE HERE* Then Set cachedInstance = Nothing
On Error GoTo errorStateDetected
cachedInstance.GetSerializedRisk "1", "1", "dummyrequest", "dummyrequest"
GoTo everythingIsFine
errorStateDetected:
Set cachedInstance = Nothing
Resume everythingIsFine
everythingIsFine:
''//I just wasted a bunch of time
End If
If cachedInstance Is Nothing Then Set cachedInstance = GetObject(ServiceAddress)
If cachedInstance Is Nothing Then Err.Raise 1, , _
"The MRLD server did not respond to the request to provide the service object."
Set GetMRLDIntegrationService = cachedInstance
End Function
答案 1 :(得分:0)
这个替代解决方案为GetService函数提供了重置缓存对象的选项(即如果发生错误),问题是我找不到使用此功能的方法,以便可以轻松地重置Faulted状态错误,但是在处理实际错误之前,其他错误不会导致冗余的错误请求。
Private Function GetMRLDIntegrationService(Optional ByVal reset As Boolean = False) As Object
Const ServiceAddress = "service:mexAddress=""net.tcp://hydfwdvweb001/Integration/MrldIntegrationService.svc/Mex""," & _
"address=""net.tcp://hydfwdvweb001/Integration/MrldIntegrationService.svc/""," & _
"contract=""IMrldSimplexIntegration"", contractNamespace=""http://tempuri.org/""," & _
"binding=""SimplexIntegration"", bindingNamespace=""http://tempuri.org/"""
Static cachedInstance As Object
If reset Then Set cachedInstance = Nothing
If cachedInstance Is Nothing Then Set cachedInstance = GetObject(ServiceAddress)
If cachedInstance Is Nothing Then Err.Raise 1, , _
"The MRLD server did not respond to the request to provide the service object."
Set GetMRLDIntegrationService = cachedInstance
End Function
调用函数:
''/*If the cached object is in an error state there's no way to detect it without making a request, but
'making even a dummy request each use just to check would waste dozens of precious seconds per request,
'so this routine carefully makes the intended request, catches the error that might occur, then resets
'the connection and tries the request again. The upside is that a service object in an error state
'will be resolved immediately and transparently by opening a new connection as needed. The downside
'is that if any other error occurs (such as a 1 minute timeout error), the first occurrence will
'be a non-breaking error and it will actually repeat the error a second time before notifying the user,
'doubling the amount of time it takes any error to propogate. (In the case of a 1 minute time-out
'occurring, the request would occur twice for a total of 2 minutes delay until the application becomes
'responsive again.)*/
Private Sub FillFromRiskID(ByVal riskID As String)
Const uName As String = "perftest1"
Const pWord As String = "****"
Dim result As String
On Error GoTo retryGet
Process_MRLD_Result GetMRLDIntegrationService().GetSerializedRisk(riskID, "1", uName, pWord)
GoTo finally
retryGet:
Resume retryGet2: 'Resets the error state so that a new error can be thrown
retryGet2:
On Error GoTo invalidConnection
Process_MRLD_Result GetMRLDIntegrationService(reset:=True).GetSerializedRisk(riskID, "1", uName, pWord)
finally:
Exit Sub
invalidConnection:
MsgBox "Error connecting to MRLD: " & Err.Description, vbCritical, "Fill From MRLD"
End Sub