1

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.

Community
  • 1
  • 1
ispiro
  • 26,556
  • 38
  • 136
  • 291
  • If `b = true` is the first line in your try block it will always run as `b = true` cannot fail. The `try` block runs until it fails. – Eli Sadoff Jun 30 '16 at 18:45
  • @EliSadoff It's `true` _before_ that line. – ispiro Jun 30 '16 at 18:46
  • But why does that matter? You can assign `b = true`, even if `b` is already `true`. That won't throw an error. – Eli Sadoff Jun 30 '16 at 18:47
  • sounds like a good time to start using the debugger i'd say – MethodMan Jun 30 '16 at 18:50
  • @GlorinOakenfoot This code is executed many times. And should have `false` from the previous time it executed. Besides the fact that this is `c#` and it will _always_ be a real value. – ispiro Jun 30 '16 at 18:50
  • 1
    "I assume that's what is causing the exception" - what exception? – Quantic Jun 30 '16 at 18:55
  • @Quantic I'm assuming an exception in the Async method is "breaking" the finally. (See the link at the end of my question.) – ispiro Jun 30 '16 at 18:56
  • You mention that this is executed many times - is this in a multi-threaded environment? – Vlad274 Jun 30 '16 at 18:58
  • @Vlad274 No. Except for the UWP Async call which is. – ispiro Jun 30 '16 at 19:01
  • You should try to make a [MCVE], because we can't assume you debugged all the rest of your code perfectly. – 31eee384 Jun 30 '16 at 19:04
  • @31eee384 There are 3 occurrences of that variable as I described. Is there ***any*** way you can see the `try` being started with `b` being `true`? (But I'll see if I can create something like what you said.) – ispiro Jun 30 '16 at 19:06
  • 2
    Is it possible that you are calling the function in [a re-entrant way](https://msdn.microsoft.com/en-us/library/mt674881.aspx)? so it is still waiting for `await SomeAsync()` to finish it gets called a 2nd time? – Scott Chamberlain Jun 30 '16 at 19:08
  • @ScottChamberlain Now _that's_ the type of comment I was hoping for! Thanks! Unfortunately, _after the iterations are done_ - `b` is still `true`. That would not be explained by that possibility. But I am going to check if that is happening. – ispiro Jun 30 '16 at 19:13
  • 2
    To address your point, what if you have a task never finishes, that would cause it to be stuck true but because it is async you can't tell anything is wrong. We really need a full example that we could copy and paste on our machines to see the behavior if you want any better answers than guesses. – Scott Chamberlain Jun 30 '16 at 19:33
  • @ScottChamberlain That's a very good point. Why not make it into an answer? I can't see a more logical reason - an exception on the Async's thread might be doing that. (By the way, I edited the edit with what I've done to avoid re-entering the Async.) – ispiro Jun 30 '16 at 19:38

1 Answers1

2

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.

Jonathan Allen
  • 68,373
  • 70
  • 259
  • 447
  • Good point. Your answer, and the same thing 2 minutes earlier in [a comment](http://stackoverflow.com/questions/38130987/finally-not-executed-because-of-async-in-try#comment63693896_38130987), made me realize that there was another pertinent detail (now edited into the question) - that `b` is left `true` _after_ all iterations. But thanks! – ispiro Jun 30 '16 at 19:21