2011-03-25 89 views
1

我正在被迫連接到正在開發的VBA工具中的某些.net服務。我使用一個函數返回緩存的實例,或者創建一個新的函數,如果它尚未創建。VBA - 在引發異常之前檢查System.ServiceModel.Channels.ServiceChannel發生故障狀態

如果出現任何錯誤與對象(如連接超時),下一次我嘗試使用它,我得到的錯誤

通信對象,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

此替代的解決方案得到GetService的功能的選項復位緩存的對象(即,如果發生錯誤),則問題是,我無法找到一種方法,使用該功能,使得故障狀態誤差可以很容易地被重置,但其他錯誤在實際錯誤得到處理之前不會導致冗餘的錯誤請求。

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 
0

這是可行的解決方案,但我試圖避免,因爲它是醜陋的,並且在大多數緩存對象沒有問題的情況下浪費時間。 GetSerializedRisk在某些情況下需要15秒才能返回,即使返回值是無效登錄或錯誤的請求標識。

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 
+0

無法做到這一點,因爲假性請求只需只要一個正常的處理,加倍每次通話的時間。 – Alain 2011-04-05 16:25:57