4

Found something yesterday that made me realise that I'm most likely still missing fundamental tidbits about C#.

I have a Stateless Service Fabric Application. I have a try-catch around the main while-loop. If I throw an exception in this loop, it breaks out of the while-loop and the service effectively stops. If I add a throw to the catch clause, the service restarts.

    protected override async Task RunAsync(CancellationToken cancellationToken)
    {
        try
        {
            long iterations = 0;
            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                await Task.Delay(TimeSpan.FromSeconds(3), cancellationToken).ConfigureAwait(false);

                // Do stuff...

                if (iterations > 4) {
                    throw new Exception();
                } 

                ServiceEventSource.Current.ServiceMessage(this.Context, $"Working-{++iterations}");
            }
        }
        catch (Exception ex)
        {
            // Log stuff...
            throw;
        }
    }

Can someone explain why this is or direct me to where I can get an answer? I couldn't find anything that explain this behaviour.

EDIT: It's not a duplicate of Is there a difference between "throw" and "throw ex"? because, as far as I can see, there it no explanation of my question, why the function is being run again. That topic is more about explaining the difference between throw and throw new respective of the stack trace.

Kagemand Andersen
  • 1,470
  • 2
  • 16
  • 30
  • 2
    Possible duplicate of [Is there a difference between "throw" and "throw ex"?](https://stackoverflow.com/questions/730250/is-there-a-difference-between-throw-and-throw-ex) – Titian Cernicova-Dragomir Jun 08 '18 at 07:44
  • 2
    Can you post the alternative code that does it differently? Currently it's hard to tell what you are asking. – nvoigt Jun 08 '18 at 07:44
  • Maybe this helps: https://stackoverflow.com/questions/881473/why-catch-and-rethrow-an-exception-in-c – daniatic Jun 08 '18 at 07:45
  • 1
    My assumption would be that this part of program is again wrapped somewhere and throwing an exception is translated to exiting with fault, while effectively returning is rendered as graceful shutdown (as the exception broke the thread of execution outside the `while` loop and therefore the method exits) – Zdeněk Jelínek Jun 08 '18 at 07:45
  • 1
    "I'm most likely still missing fundamental tidbits about C#", I wouldn't call that 'fundamental', exception handling with async code is made to look easy, but it's quite subtle and not trivial actually. – Pac0 Jun 08 '18 at 07:46
  • Which exception is being thrown? Is it the one from `cancellationToken.ThrowIfCancellationRequested();` or the one from `throw new Exception();`? This makes a difference. – Matthew Watson Jun 08 '18 at 07:54
  • It's the `throw new Execption()`. It was to simulate an error. – Kagemand Andersen Jun 08 '18 at 08:08

1 Answers1

5

With what you have described, we have two options:

  1. You rethrow the exception and the RunAsync Task is failed with that exception
  2. You don't rethrow the exception and the RunAsync Task is completed gracefully (the caught exception broke the while loop and so the method exits).

For the first case, the Service Fabric Stateless Service RunAsync doc further details the behavior when an exception is encountered, namely that exceptions derived from FabricException will cause a restart while others are either intended or unexpected service abortion and cause it to stop.

The graceful completion logically means that the service successfully finished executing and will be shut down as per Service Fabric Reliable Services Lifecycle doc.

Zdeněk Jelínek
  • 2,611
  • 1
  • 17
  • 23
  • Ah, that makes more sense then. I thought I had misunderstood what throwing and re-throwing did in C#. No wonder I couldn't find a satisfying answer. Thanks! – Kagemand Andersen Jun 08 '18 at 09:08