"finally" not executed because of Async in "try"? - c#

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.

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.

Related

Try-Catch Loop until success

bool hasCopiedArtikelnum = false;
while (hasCopiedArtikelnum == false)
{
try
{
artikelnum = Clipboard.GetText();
hasCopiedArtikelnum = true;
}
catch {}
}
I want the program to keep looping until he has successfully copied. Does putting other things in the "try" work? Or will the programm also >>try<< to set hasCopiedArtikelnum to true?
It seems what you really want to do is wait until the user has copied something to the clipboard and then check whether there is text contained in the clipboard using Clipboard.ContainsText (as already suggested by #CodeCaster and #PatrickHofman).
You can receive clipboard events as described in an answer to this question: Clipboard event C#.
Such an approach is much better because you a) won't be using exceptions for control flow and b) reduce CPU load significantly by avoiding to permanent polling of the clipboard.
The while loop while continue to execute until hasCopiedArtikelnum is true.
This means you can put anything into the try block and it will keep iterating until everything completes, at long as hasCopiedArtikelnum = true is at the end.
If Clipboard.GetText() throws an exception when it's not ready to complete, the execution will jump hasCopiedArtikelnum and it will remain false
Yes, you can catch all exceptions using catch (Exception) {} and it will continue. I advice to use a maximum number of tried though, to prevent this action from hanging.
I guess you are solving a problem with retrieving text. Maybe there are other ways to do so, maybe you can sleep for X milliseconds, use a timer to do it once a X seconds for example, etc. I guess there is another solution you are looking for. This code will hang your process until it succeeds retrieving the text. Are you looking for some event maybe?
Also it is better not to rely on an exception if you can, possibly while (!Clipboard.ContainsText(TextDataFormat.Text)), as CodeCaster suggested it a better solution.

BackgroundWorker problems on exit

I am having a bit of a conundrum here, and would like to know a couple of things:
Am i doing this wrong?
What is the expected behaviour of a backgroundworker in different scenarios...
If possible, get an answer as to why i am getting specific behaviour would be nice...
For point 1, and ultimately 3 as well, i will explain what i am doing in Pseudo-Code so that you have the details without actually spitting out thousands of lines of code. While i write this post, i will look at the code itself to ensure that the information is accurate as far as when and what is happening. At the very end, i will also detail what is happening and why i am having issues.
Pseudo-Code details:
I have a main UI thread (WinForms form), where after selecting a few configuration options you click a button.
This button's event does some preliminary setup work in memory and on the file system to get things going and once that's done fires off ONE backgroundworker. This backgroundworker initializes 5 other backgroundworkers (form scope variables), sets their "Done" flags (bool - same scope) to true, sets their "Log" vars to a new List<LogEntry> (same scope) and once that's done calls a method called CheckEndConditions. This method call is done within the DoWork() of the initial backgroundworker, and not in the RunWorkerCompleted event.
The CheckEndConditions method does the following logic:
IF ALL "Done" vars are set to True...
Grab the "Log" vars for all 5 BWs and adds their content to a master log.
Reset the "Log" vars for all 5 BWs to a new List<LogEntry>
Reset the "Done" vars for all 5 BWs to False.
Call MoveToNextStep() method which returns an Enum value representative of the next step to perform
Based on the result of (5), grab a List<ActionFileAction> that needs to be processed
Check to ensure (6) has actions to perform
If NO, set ALL "Done" flags to true, and call itself to move to the next step...
If YES, partition this list of actions into 5 lists and place them in an array of List<ActionFileAction> called ThreadActionSets[]
Check EACH partitioned list for content, and if none, sets the "Done" flag for the respective thread to true (this ensures there are no "end race scenarios")
Fire off all 5 threads using RunWorkerAsync() (unless we are at the Finished step of course)
Return
Each BW has the exact same DoWork() code, which basically boils down to the following:
Do i have any actions to perform?
If NO, set my e.Result var to an empty list of log entries and exit.
If YES, loop for each action in the set and perform 4-5-6 below...
What context of action am i doing? (Groups, Modules, etc)
Based on (4), what type of action am i doing? (Add, Delete, Modify)
Based on (5), perform the right action and log everything you do locally
When all actions are done, set my e.Result var to the "log of everything i've done", and exit.
Each BW has the same RunWorkerCompleted() code, which basically boils down to the following:
TRY
From the e.Result var, grab the List<LogEntry> and put it in my respective thread's "Log" var.
Set my respective "Done" var to true
Call CheckEndConditions()
CATCH
Set my respective "Done" var to true
Call CheckEndConditions()
So that is basically it... in summary, i am splitting a huge amount of actions into 5 partitions, and sending those off to 5 threads to perform them at a faster rate than on a single thread.
The Problem
The problem i am having is that i often find myself, regardless of how much thought i put into this for race scenarios (specifically end ones), with a jammed/non-responsive program.
In the beginning, i had setup my code inefficiently and the problem was with End Race Scenarios and the threads would complete so fast that the last call made to CheckEndConditions saw one of the "Done" vars still set to false, when in fact it wasn't/it had completed... So i changed my code to what you see above which, i thought, would fix the problem, but it hasn't. The whole process still jams/falls asleep, and no threads are actually running any processing when this happens which means that something went wrong (i think, not sure) with the last call to CheckEndConditions.
So my 1st question: Am i doing this wrong? What is the standard way of doing what it is i want to do? The logic of what i've done feels sound to me, but it doesn't behave how i expect it to so maybe the logic isn't sound? ...
2nd question: What is the expected behaviour of a BW, when this scenario occurs:
An error occurred within the DoWork() method that was un-caught... does it fire off the RunWorkerCompleted() event? If not, what happens?
3rd question: Does anyone see something obvious as to why my problem is occurring?
Thanks for the help!
Reposting my comment as answer per OP's request:
The RunWorkerCompleted event will not necessarily be raised on the same thread that it was created on (unless it is created on UI thread) See BackgroundWorker RunWorkerCompleted Event
See OP comments for more details.

Strange if-statement behavior with zero value double

Would anyone care to explain to me how the value of this.oBalance.QouteBalance is evaluated to be true for being less than zero when it clearly isn't? Please see image below.
Am I missing something fundamental when it comes to comparing doubles in C#??
public double QouteBalance { get; set; }
UpdateBalance_PositionOpenned() is not being called in a loop, but is being called as part of a more complex event driven procedure that runs on the ticks of a timer (order of milliseconds)
EDIT: Pardon the code if it's messy but I couldn't edit it as this was a run-time error after quite a long run-time so was afraid wouldn't be able to recreate it. The Exception message is not correct and just a reminder for myself. The code after the exception is code I forgot to comment out before starting this particular run.
EDIT 2: I am building and running in Release Mode.
EDIT 3: Pardon my ignorance, but it would seem that I am in fact running in a multi-threaded environment since this code is being called as part of a more complex object method that gets executed on the ticks (Events) of a timer. Would it possible to ask the timer to wait until all code inside its event handler has finished before it can tick again?
EDIT 4: Since this has been established to be a multi-threading issue; I will try to give wider context to arrive at an optimized solution.
I have a Timer object, which executes the following on every tick:
Run a background worker to read data from file
When background worker finishes reading data from file, raise an
Event
In the event handler, run object code that calls the method below
(in the image) and other multiple routines, including GUI updates.
I suppose this problem can be avoided by using the timer Tick events to read the from file but changing this will break other parts of my code.
You're accessing shared variables from multiple threads. It's probably a race condition where one thread has thrown the error but by the time the debugger has caught and attached, the variable's value has changed.
You would need to look at implementing synchronizing logic like locking around the shared variables, etc.
Edit: To answer your edit:
You can't really tell the timer to not tick (well you can, but then you're starting and stopping and even after calling Stop you might still receive a few more events depending on how fast they are being dispatched). That said, you could look at Interlocked namespace and use it to set and clear and IsBusy flag. If your tick method fires and sees you're already working, it just sits out that round and waits for a future tick to handle work. I wouldn't say it's a great paradigm but it's an option.
The reason I specify using the Interlocked class versus just using a shared variable against comes down to the fact you're access from multiple threads at once. If you're not using Interlocked, you could get two ticks both checking the value and getting an answer they can proceed before they've flipped the flag to keep others out. You'd hit the same problem.
The more traditional way of synchronizing access to shared data member is with locking but you'll quickly run into problems with the tick events firing too quickly and they'll start to back up on you.
Edit 2: To answer your question about an approach to synchronizing the data with shared variables on multiple threads, it really depends on what you're doing specifically. We have a very small window into what your application is doing so I'm going to piece this together from all the comments and answers in hopes it will inform your design choice.
What follows is pseudo-code. This is based on a question you asked which suggests you don't need to do work on every tick. The tick itself isn't important, it just needs to keep coming in. Based on that premise, we can use a flagging system to check if you're busy.
...
Timer.Start(Handle_Tick)
...
public void Handle_Tick(...)
{
//Check to see if we're already busy. We don't need to "pump" the work if
//we're already processing.
if (IsBusy)
return;
try
{
IsBusy = true;
//Perform your work
}
finally
{
IsBusy = false;
}
}
In this case, IsBusy could be a volatile bool, it could be accessed with Interlocked namespace methods, it could be a locking, etc. What you choose is up to you.
If this premise is incorrect and you do in fact have to do work with every tick of the timer, this won't work for you. You're throwing away ticks that come in when you're busy. You'd need to implement a synchronized queue if you wanted to keep hold of every tick that came in. If your frequency is high, you'll have to be careful as you'll eventually overflow.
This isn't really an answer but:
UpdateBalance_PositionOpenned() is not being called in a loop, but is
being called as part of a more complex event driven procedure that
runs on the ticks of a timer (order of milliseconds)
see:
Multi-threading? – abatishchev 30 mins ago
Tight timer driven event-loop on the order of milliseconds probably has all the problems of threads, and will be almost entirely impossible to trouble-shoot with a step-through debugger. Stuff is happening way faster than you can hit 'F10'. Not to mention, you're accessing a variable from a different thread each event cycle, but there's no synchronization in sight.
Not really a full answer but too much for a comment
This is how I could code defensively
Local scope leads to less unexpected stuff
And it make code easier to debug and test
public void updateBalance(double amount, double fee, out double balance)
{
try
{
balance = amount * (1.0 + fee);
if (balance < 0.0) balance = 0.0;
}
catch (Exception Ex)
{
System.Diagnostics.Debug.WriteLine(Ex.Message);
throw Ex;
}
}
Value type is copied so even if then input variable for amount changed while the method was executing the value for amount in the method would not.
Now the out balance without locks is a different story.

Overhead in returning from a method

I have a method A() that processes some queries. This method, from opening bracket to just before its return statement, times at +/-70ms. A good 50% of which comes from opening the connection, about 20% comes from the actual queries, 5-10% is used by some memory access, the rest is (probably) used for disposing the connection, commands and reader.
Although this big chunk of time used for handling the connection is annoying enough, what bothers me more is that when I call A() from method B():
B()
{
var timer = Stopwatch.Startnew()
A();
timer.Stop(); // elapsed: +/- 250ms
Debugger.Break();
}
Another 180ms of lag gets added and I can't seem to figure out why. I already tried having A return null, which changes nothing.
The only disk I/O and networking happens in A. I thought the transfer from disk and network to local memory should've happened in A, and therefore a call to A from B should not be influenced by this, but apparently this is not the case? Is this network latency I'm experiencing here? If so, then why does this also happen when I just let B return null?
I have no other explanation at the moment...
Everything resides in the same assembly,
Measuring without a debugger attached changes nothing,
Returning 'null' immediately show 0 ms, returning null instead of the normal return value changes nothing (but enforces the idea this is somehow related to latency).
A is roughly implemented as follows, like any simple method accessing a database. It's contrived, but shows the basic idea and flow:
A()
{
var totalTimer = Stopwatch.StartNew();
var stuff = new Stuffholder();
using(connection)
{
using(command)
{
using(reader)
{
// fill 'stuff'
}
}
}
totalTimer.Stop(); // elapsed: +/- 70ms
return stuff;
}
Any ideas?
The overhead that you are seeing is due to just-in-time compilation. The first time method B() is called method A() has not been natively compiled (it is partially compiled in the dll as IL), so you see a slight lag while the compiler compiles A() into machine code.
When profiling a method call it is important to call the method a large number of times and take the average time (discarding the first call if you like, although over enough calls the compilation overhead should become insignificant).
Since you have database access in A() you might be suffering from network name resolution issues, so your first call take a while longer to execute.

correct way to handle exit from infinite loop in c#

In my apps i find the need to have infinite while loops mostly to do some repeated action continuosly unless another event takes place so what i am doing is
while(chkFlag)
{
//do something here which takes around 30 seconds
}
Then in some other event say a button press to stop the loop i do
chkFlag = false;
Now this does the work but the problem is this does not stop the loop instantaneously as the chkFlag is checked only after the complete execution of the loop takes place. So can anybody please tell me how i can exit a loop instantaneouly based on an event.
The "blocking" code should likely be moved into some kind of worker thread (which can be terminated and/or have the results discarded). If using a BackgroundWorker (recommended, as it makes this simple), there is built-in support to handle a cancel operation.
Then the loop can either be moved inside the BackgroundWorker or the completion (RunWorkerCompleted) event of the worker can trigger the next worker to start (which causes an implicit loop).
Happy coding.
There are more "aggressive" ways of terminating/signaling a thread; but suggesting these would require more information than present.
you can't make it exit instantly (well, you could run the loop in a new thread and Abort it, if it's really safe to have an exception thrown from it at any time), but you could scatter if(!chkFlag) break; at various points within the loop that it's safe to exit. The usual method of doing this is to use a BackgroundWorker or a CancellationToken rather than a simple boolean flag.
Of course, it will still need to be run in another thread so that the button event can run at all. BackgroundWorker will take care of this automatically.
You are looking for break;.
I suppose, based on the anonymous downvoter, I should elaborate. The syntax above will immediately exit the loop that you are in (it works in the other loops as well; it's probably worth noting that continue exists to restart the loop at the beginning, which will perform increment logic in for-style loops).
How you decide to execute break is up to you, but it must be within the loop itself.
There are multiple approaches to this, such as placing checks for the event within the loop and calling break; if it occurs. Others have noted the other approaches with BackgroundWorkers and Cancel Tokens (this is preferred given it's not within the loop).
Is it possible you want to use a new thread? What are you doing for 30 seconds in the loop. Sounds like maybe there's a better design to use.
Have you considered using a timer, or setting up an event handler?

Categories

Resources