Reputation: 27673
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
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