1

I've an class TCPDataLink implementing some TCP features using Socket. I also have an IOManager which does some logging when an error is thrown (on all my DataLink).

The problem is that I cannot find a way to catch exceptions of Socket event handlers from my IOManager Class. I do not want to inject Logger dependency inside my TCPDataLink class since I don't wan't to repeat the logging code in all my DataLink classes.

Example in a normal case :

// IOManager Class call in a normal case
try
{
  tcpInstance.DoSomething
}
catch (MyCustomEx e)
{
  // Log the problem
  Logger.log(e.ToString());
}

In my problematic case :

// TCPDataLink.cs
...
socket.OnConnection += ConnectionHandler // Cannot try/catch or whatever
...

void ConnectionHandler(...)
{
  // Code throwing Exceptions
}

According to this thread, external try/catch is not an option. So I've to catch Exception inside my ConnectionHanlder and... ?

What's my best alternative to log from my IOManager whitout the possibility to catch Exception ?

Thanks,

Community
  • 1
  • 1
Nicolas Voron
  • 2,916
  • 1
  • 21
  • 35

2 Answers2

2

The best way is to catch excpetion actually. Orchestrating your app workflow with expected exceptions handling is sometihng that you normally do in IO interactions, often there is no other way to handle that correctly.

So just handle it within your ConnectionHandler with some try/catch/throw sequence. May be, do not raise an exception one time it catched, but just handle it.

Tigran
  • 61,654
  • 8
  • 86
  • 123
  • Yes, I already handle the exception (not reported in my example case, i'll update my post). My question is what's the best method for "expected exceptions handling" in c# (in other word how notify my `ConnectionHandler` ? I can do it with events, but since events inheritance is a pain, I'm hoping that an other solution exists. – Nicolas Voron Dec 03 '12 at 14:36
  • @NicolasVoron: can use state variable instead. – Tigran Dec 03 '12 at 14:37
  • Could you elaborate a little more on this please ? – Nicolas Voron Dec 03 '12 at 14:38
  • decalre some Error (bool, say) variable that indeicates that error happens, or enumeration with error codes, and set that code in ConnectionHandler, so it knows that something went wrong. – Tigran Dec 03 '12 at 14:40
  • If I understand right, you suggest that the ConnectionHandler will be notify of the error through a `PropertyChanged` event (on an enum/bool representing the error) ? Not bad – Nicolas Voron Dec 03 '12 at 14:47
  • @NicolasVoron: just an idea. You have to think what fits best your needs. – Tigran Dec 03 '12 at 14:49
  • Yes, I was secretly hoping that a power/magical feature can resolve my try/catch problem without dealing with events again, but it seems that there isn't an other/better solution :( – Nicolas Voron Dec 03 '12 at 14:54
  • well, as I said, you can hold on the datastructures and fields, instead of propogating eent along your types. But with events, the good, it's event driven in all sences. – Tigran Dec 03 '12 at 14:55
0

Events should generally not allow the escape of any exceptions less severe than CpuOnFireException. If an event represents an action that may or may not succeed, and whose failure needs to be relayed to the calling code, the event handler should catch all less-severe exceptions and pass information about them via the "event arguments" parameter. Of course, this creates an obligation on the part of the code raising the event to check whether any exceptions occurred; it may also create an obligation on the part of the event handlers to check whether problems in previous handlers should cause an event handler to ignore the current event.

While using MulticastDelegate to handle event subscriptions may seem simple and easy, an exception which occurs while processing one part of a MulticastDelegate will cause other parts to be skipped; in many cases, having an event get skipped may turn what would otherwise have been a recoverable exception into an unrecoverable one (e.g. two collections which are supposed to be kept updated so as to match each other may get out of sync if an update notification gets skipped). While it's possible to decompose a MulticastDelegate into a list of method pointers and targets, it would be easier to use some other data type like an EventHandler<T>[] to hold the event list and not bother making any multicast delegates.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • Interesting. Can you provide a sample code based on my example ? – Nicolas Voron Dec 04 '12 at 08:27
  • @NicolasVoron: If the nature of your connection object is such that everything will work perfectly unless or until something happens that makes the wheels fall off, at which point the object may be considered permanently useless, I would suggest perhaps having a `ConnectionFailureCause` property which would initially be null, but would be set the first time something goes wrong (all subsequent attempts to do something with the object should throw an immediate exception, but there's probably no need for the connection object to log them). The object might include an exception, but should... – supercat Dec 04 '12 at 16:14
  • ...also include context about where it was caught. The `Exception` object reports the location of the throw *relative to the catch*, which is great if it's being analyzed by the code that caught it, but not so great if it's being stored for analysis by code running in a completely different context. – supercat Dec 04 '12 at 16:17