ispiro
ispiro

Reputation: 27673

"finally" not executed because of Async in "try"?

I have a bool (b) which appears only twice in my code (besides its declaration):

try 
{
    b = true;
    //code including await SomeAsync();
}
catch {  }
finally { b = false; }

yet sometimes the try block is started with b being true (-before b = true) which should never be happening because the declaration leaves it false, as does the previous finally. At some point, this code is executed in a loop, which in some cases is iterating quickly and SomeAsync() is trying to use too much memory. I assume that is throwing an exception of a type that can "break" a finally. (b is always false as expected when there's only a normal amount of data for SomeAsync() to process.)

I've tried verifying what Visual Studio shows me with Debug.WriteLine() both after the try and after the finally, and also by appending to a string a different character in those places, but then the finally was executed. So I assume that the slow delay was enough to prevent the exception.

Is this really possible? (Any ideas on how to verify it or fix it so that the finally always runs?)

(finally blocks can fail - cases: Conditions when finally does not execute in a .net try..finally block )

EDIT

A good point was raised in a comment and an answer - that this code might be executed several times concurrently during the awaits. Unfortunately, there's another detail (that those answers made me aware is pertinent) - after all iterations - the state is that b is true. That is not explained by concurrency. I have also added an if (b) return; before the try block (to avoid calling the Async while the previous is running). Still getting left with a true b after all iterations are done.

Upvotes: 1

Views: 2695

Answers (1)

Jonathan Allen
Jonathan Allen

Reputation: 70307

This is a pretty common mistake. The code you showed can be run multiple times concurrently. For example, it you attach it to a button click event, the user can click the button ten times in a row, causing ten copies of the function to run at nearly the same time.

In this example they won't literally run at the same time, being ties to the UI thread, but they can overlap with the scheduler jumping from one instance to the next every time it sees an await statement.


If you are running this in the background (e.g. Thread.Start) then each instance will get its own thread and you really will have multiple copies running at the same time.

Upvotes: 2

Related Questions