(我不确定这是否更适合代码审查)
我使用在内部维护DCOM连接的(闭源)库,此DCOM连接转到本地计算机上运行的服务。用户(而不是通过我们的应用程序)经常停止并启动此服务。
不幸的是,看起来DCOM相关的异常会影响到我们的应用程序。
似乎没有任何方式在库中给出以确定与服务的连接是否仍然有效,现在只知道我们已经失去与服务的连接以尝试做某事并让它抛出异常(其类型变化很大)。
尝试使其更易于管理的最佳尝试是将通常由DCOM引起的异常与由配置问题引起的异常分开....
以下是代码最终结果的样本:
Private Sub Initialize()
Dim ParametersToDComObject As Integer
Try
Dim HRESULT = ClassThatUsesDCOMInstance.InitDCOMObject(ParametersToDComObject)
Console.WriteLine("Connected to service through DCOM.")
Catch Ex As Exception
If (IsLikelyCausedByConnectionLoss(Ex)) Then
'in this case, throw to make sure that we don't try to continue assuming that the connection went through
'I'm not sure what type of exception would be best to throw here,
'this would occur if the service is not running; the calling function
'would notify the user that there's a problem
Throw New InvalidOperationException(Ex.Message, Ex)
Else
Throw
End If
End Try
End Sub
Private Sub ReadDataFromClass(EntryName As String)
Try
Dim HRESULT As Integer = ClassThatUsesDCOMInstance.ReadEntry(EntryName)
Catch Ex As Exception
If (IsLikelyCausedByConnectionLoss(Ex)) Then
'If the service is stopped, from the application's perspective every method in
'this class suddenly starts failing, and it won't start working again until a new instance
'of the class that uses DCOM is made.
'
'So the sub below attempts to make sure that our application knows that the methods in this class
'won't work anymore... (I usually set ClassThatUsesDCOMInstance to Nothing after cleaning up)
'
'Sometimes I just have to "reconnect", but the tricky thing is, the only recovery option may be to
'(re)start the service that's providing the DCOM object; it seems best to notify the
'user in this case since in most cases the user knowlingly stopped the service, it's
'normal to stop the service to configure it
CleanupAfterConnectionLoss()
Throw New InvalidOperationException(Ex.Message, Ex)
End If
If (TypeOf (Ex) Is TheLibraryDefinedThisException) Then
'let's say that the library throws this if we try to read an entry that doesn't exist (e.g., if the configuration has changed)
'we can't fix the problem automatically, but we can notify the user that something has changed external to this program, so they can
'either fix the service or edit their configuration for our application
Console.WriteLine("Entry " & EntryName & " could not be read " & Ex.Message & " check that the entry is defined on the service")
Else
Throw
End If
End Try
End Sub
Private Function IsLikelyCausedByConnectionLoss(ThrownException As Exception) As Boolean
'I'm thinking it's best to put this in a separate function because development has gone like this:
'
' 1. the provided documentation does not give any information about what methods will throw what kinds of exceptions
' All functions return **HRESULTs**, I assumed that there weren't going to be /any/ exceptions
'
' It turns out the HRESULTs cover certain errors and exceptions cover certain errors, with some overlap...
'
' 2. I determined experimentally during testing that it throws a <Library Defined Exception> if I give it an invalid entry name, okay, I can work with that
'
' 3. I determined experimentally that if I stop the service while we're connected, all functions throw a COMException, not convenient but ok.
'
' 4. Weeks later, I figure out that it also occasionally throws InvalidComObjectException if the service is stopped under the same situation
'
' 5. Weeks later, I find out that it occasionally throws ApplicationExceptions under the same situation
'
' 6. Weeks later, I find out that certain functions will additionally throw an InvalidCastException
'
' note that there's no change in input to the library to cause these different exceptions, and the only cause
' is the loss of connection to the DCOM server
'
' in the last code setup I had to manually update every try/catch block that had anything to do with this library every time
' I found something new...
If (TypeOf (ThrownException) Is InvalidCastException) Then
'I really don't like catching this, but I get this if the COM object fails to bind to the interface,
'which occasionally happens if the service isn't there or isn't set up right
Return True
ElseIf (TypeOf (ThrownException) Is ApplicationException) Then
'I really don't like catching this either, same reason as above
Return True
'I don't believe this is an exhaustive list of every exception that can be thrown due to loss of DCOM connection,
'please let me know if you know of more exceptions that can be thrown...
ElseIf (TypeOf (ThrownException) Is Runtime.InteropServices.COMException) Then
Return True
ElseIf (TypeOf (ThrownException) Is Runtime.InteropServices.InvalidComObjectException) Then
Return True
Else
Return False
End If
End Function
但是,我觉得这对于这个问题来说是一个糟糕的解决方案。这似乎不仅仅是吞下所有例外情况,而且不是太多。
编辑: