Skip to content

Instantly share code, notes, and snippets.

@clemensv
Created August 30, 2012 20:40
Show Gist options
  • Save clemensv/3540372 to your computer and use it in GitHub Desktop.
Save clemensv/3540372 to your computer and use it in GitHub Desktop.
Yes, a goto courtesy of async/await's scoping issues with "catch".
// The scoping model in "catch" doesn't allow for async/await handling because
// catch needs to be able to rethrow without messaging up the stack frame, i.e. "throw;"
// There's obviously an alternate non-goto solution here with a result variable and a
// subsequent switch on that result, but if you code that up, the switch looks like
// a longer, uglier variant of the gotos.
static async Task LoopedReceive(Func<Task<BrokeredMessage>> receiveCallbackAsync,
Func<BrokeredMessage, Task<bool>> messageReceivedCallbackAsync,
CancellationToken token)
{
bool continueLoop = true;
while(continueLoop && (!token.CanBeCanceled || !token.IsCancellationRequested))
{
try
{
var message = await receiveCallbackAsync();
if (message != null)
{
try
{
continueLoop = await messageReceivedCallbackAsync(message);
}
catch (Exception e)
{
Trace.TraceError(CallbackThrewExceptionExceptionText, e);
goto Abandon;
}
continue;
Abandon:
AbandonMessage(message);
continue;
}
}
catch (MessagingException me)
{
if (!me.IsTransient)
{
throw;
}
}
}
}
static async void AbandonMessage(BrokeredMessage message)
{
try
{
await message.AbandonAsync();
}
catch (Exception e)
{
if (e.IsFatal())
{
throw;
}
Trace.TraceError(UnableToAbandonMessageExceptionText, e);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment