I'm new to c# working with a windows service which has a timer but the autoreset is set to false so it supposed to run an infinite loop Querying to a Sql database. If the SQL returns records the process runs fine, but when no records are found the service throws an exception after 10 - 12 minutes, System.StackOverflowException was unhandled which is not clear (to me). Not sure how to better capture the issue or how to correct. Any assistance would be apprecieated.
`private static bool LoadRequests()
{
// check for requests will return combined Header/Detail record
bool RequestsLoaded = false;
string XMLURL = "";
string currentWorkingDirectory = "";
string text = "";
int rowcounter = 0;
try
{
//Summary List will be a subset of requested items, by ID#
var SummaryInfoList = new List<SummaryInfo>();
ReqHdrPlusDtlList myReqHdrPlusDetailList = new ReqHdrPlusDtlList();
List<ReqHdrPlusDtl> myReqHdrPlusDetailList = myReqHdrPlusDetailList.GetReqHdrPlusDtlList();
if (myReqHdrPlusDetailList != null && myReqHdrPlusDetailList.Count > 0)
{
// set check for last record
ReqHdrPlusDtl last = myReqHdrPlusDetailList.Last();
// scroll through each record in Request List
foreach (ReqHdrPlusDtl detailrec in myReqHdrPlusDetailList)
{
/// process id records ...
/// ...
} // exit for/each
}
else
{
//no records in list sleep for half a second before proceeding
Thread.Sleep(500);
text = "Done sleeping...";
WriteToAppLog(text);
}
//As soon as one request is fully processed, get the next pending record.
LoadRequests();
} // ends try
catch (Exception e)
{
WriteErrorMessageToAppLog(e);
RequestsLoaded = false;
}
return RequestsLoaded;
}`
When you look for the exception in the docs it states the following.
The exception that is thrown when the execution stack overflows because it contains too many nested method calls.
This exception often happens when you have an infinite loop, like in your code.
You are working with recursion (Recursion is an important programming technique that causes a function to call itself, source).
Because you keep calling your own function over and over again, you keep building up the stack, until it overflows.
You should rewrite the function so that it will actually end.
I suggest using a DispatcherTimer to call your function every 500ms, instead of Thread.Sleep() because Thread.Sleep() also blocks any execution of code on that thread.
private DispatcherTimer _dispatcherTimer;
private void SetUpTimer(){
_dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
_dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
_dispatcherTimer.Interval = TimeSpan.FromMilliseconds(500);
_dispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
LoadRequests();
}
Note: I didn't test the code, and I haven't written c# in a while, though it should help you get there
You are using a recursive call which is causing the stack overflow problem. Get rid of the recursive call to correct. Possibly make a control loop as follows:
bool success = true;
while(success)
{
try
{
LoadRequests();
Thread.Sleep(500);
}
catch (exception ex)
{
//Log Error ex.Message;
success = false;
}
}
Once you eliminate calling the function inside of itself, the stack overflow problem should be resolved.
Edit
One other comment, is the recursion is never-ending (no control statement to block execution) which is a big no-no. If you have to use recursion then there must be a way to exit the method (a stop condition). All that being said, almost every recursive problem can be solved iteratively and it can be very beneficial to do so, as it consumes significantly less system resources. The above listed code would be an iterative solution.
Related
I am working with a large and complex event driven body of code and there are piles of opportunity to accidentally create a recursive condition.
Sometimes the recursive condition is temporary and the application catches up with itself but even that usually creates unnecessary lag. Other times it creates a stackoverflow which is often very difficult to debug when it happens at a client site.
I would like to have a way to either blacklist or whitelist sections of code that are permitted to recurse. If the recursive condition happens during DEV then I want it to assert so that I can correct the code.
What I am considering is having the application examine its own stack to ensure that the method it just entered is not already on the stack.
Any pointers would be appreciated.
Note: This is for a Web Application but I have run into this challenge in multiple environments.
You can inspect stack like this:
[MethodImpl(MethodImplOptions.NoInlining)]
// optionally decorate with Conditional to only be used in Debug configuration
[Conditional("DEBUG")]
public static void FailIfCallerIsRecursive() {
var trace = new StackTrace();
// previous frame is the caller
var caller = trace.GetFrame(1).GetMethod();
// inspect the rest
for (int i = 2; i < trace.FrameCount; i++) {
// if found caller somewhere up the stack - throw
if (trace.GetFrame(i).GetMethod() == caller)
throw new Exception("Recursion detected");
}
}
Then just call it a the beginning:
void MyPotentiallyRecursiveMethod() {
FailIfCallerIsRecursive()
}
But note that it's quite expensive. However since you are going to use that only in dev (debug) configuration - why not. You can also modify it a bit to throw only when certain level of recursion is detected (so caller appears X time up the stack).
You could call the RuntimeHelpers.EnsureSufficientExecutionStack method and then catch the InsufficientExecutionStackException that is thrown if the next method call would cause a (not catchable) StackOverflowException.
You could create an extension method for it:
public static T EnsureSafeRecursiveCall<T>(this Func<T> method)
{
try
{
RuntimeHelpers.EnsureSufficientExecutionStack();
return method();
}
catch (InsufficientExecutionStackException ex)
{
string msg = $"{method.Method.Name} would cause a {nameof(StackOverflowException)} on the next call";
Debug.Fail(msg);
// logging here is essential here because Debug.Fail works only with debug
throw new StackOverflowException(msg, ex); // wrap in new exception to avoid that we get into this catch again and again(note we are in a recursive call)
}
}
Now your original method remains almost unchanged:
public static IEnumerable<T> YourRecursiveMethod<T>(IEnumerable<T> seq)
{
var method = new Func<IEnumerable<T>>(() => YourRecursiveMethod(seq));
return method.EnsureSafeRecursiveCall();
}
I have a CodedUI test. It sporadic fail by exception(can't focus element). Can I do something like this
[TestMethod]
public void MySporadicFailedTest()
{
try {
//Some Test action
}
catch((Exception ex)) {
if (ex is System.Exception.ElementNotFocused){
//retry test
}
}
}
This is something I deal with frequently when writing Coded UI tests. I almost always end up writing a simple extension method to handle retrying specific actions (not the entire test!). Sometimes, especially on pages with weird, non-standard markup or lots of AJAXy things happening, you'll just hit a situation where an action will fail one second because something isn't ready yet, then pass the next.
public static class TestRetryExtensions
{
public static void WithRetry<T>(this Action thingToTry, int timeout = 30) where T: Exception
{
var expiration = DateTime.Now.AddSeconds(timeout)
while (true)
{
try
{
thingToTry();
return;
}
catch (T)
{
if (DateTime.Now > expiration)
{
throw;
}
Thread.Sleep(1000);
}
}
}
}
Then, within my actual test:
uiMap.ClickSomeThing();
uiMap.EnterSomeText();
Action clickSomeOtherThingAction = () => uiMap.ClickSomeOtherThingThatFailsForNoReason();
clickSomeOtherThingAction.WithRetry<UITestControlHiddenException>(60);
It tries to perform the action. If it fails with an exception that you aren't aware of being an occasional "normal" thing, it throws the exception as normal. If it fails with an exception that you're telling it to retry on, it will keep trying that action (with a 1 second delay between retries) until the timeout is exceeded, at which point it just gives up and rethrows the exception.
As long as you can catch which ever exception is thrown, you can wrap your test code in a retry loop. Then it will try the test code a certain number of times before giving up:
for (var i = 0; i < TimesToRetry; i++)
{
try{
//perform test
//test ran correctly - break out loop to end test
break;
}
catch(Exception){
//might want to log exception
}
}
If the codedUI test continuously failing without proper reason you can added some code to enhance the test and make it fail safe. If test failing specifically when focusing to an element try to give focus to upper level element first and then try focusing child elements. This LINK may help you to write fail safe test cases.
we can include below line of code in test clean up method to re run the failed script
if (TestContext.CurrentTestOutCome==TestContext.unittestoutcome.failed)
{
var type=Type.GetType(TestContext.FullyQualifiedTestClassName);
if (type !=null)
{
var method=Type.GetMethod(TestContext.TestName);
var event=Activator.CreateInstance(type);
}
method.invoke(event);
}
I got a function named inner_logic() that can throw many types of exception , each of one of two types: critical and non-critical. The logic of inner_logic() includes an "infinite" loop, so in case of a non-critical exception I'd wish to step back in to it. At that point you can ask why not catching the non-critical exception within the loop, and the reason is that it's an abstract class with a few inheritors, each have a unique loop. for clarification, what I want to do is something like:
public void logic()
{
try
{
inner_logic();
}
catch (non_critical e)
{
// log
logic();
}
catch(critical e)
{
// log
return;
}
public virtual void inner_logic(){}
As far as I can tell, I seems that it should work, and that all calls are "catchable", but it feels kinda hackish.
My Question is: Is there a better way for doing that, or a reason I should reconsider my suggestion?
I did something similar in the past. I try to avoid recursion so I did a loop instead.
public void logic()
{
bool running = true;
while(running)
{
running = false;
try
{
inner_logic();
}
catch(non_critical e)
{
running = true;
}
}
}
Actually, I did it a bit diffrently. Instead of a boolean, I counted the number of non_critical errors. If the number exceded 3 then I handled it as a critical error.
You should not do it this way, as if the current state of the application means that the non- critical exception is thrown repeatedly, a stack overflow exception will occur.
Catch the exception outside the method and repeat if needed.
It feels to me like it should just be looping:
while (true) // Or probably have a maximum number of retries
{
try
{
// Logic
// Break out of the loop by returning if we succeed
return;
}
catch (NonCriticalException e)
{
// Log, then let the loop continue
}
catch (CriticalException e)
{
// Log, then rethrow (in preference to returning)
}
}
With your original approach, if the non-critical exception just keeps happening, you'll get a StackOverflowException. I would definitely suggest adding a maximum retry count though. (Keeping track of the number of retries is good for logging, too.)
I'm trying to concatenate some data within a foreach iterator within a using block. Unfortunately, for some reason, any statements I insert into (or after) the using block after the foreach fail to fire.
Source:
static void sensor_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
{
using (var depthFrame = e.OpenDepthImageFrame())
{
if (depthFrame == null)
return;
short[] bits = new short[depthFrame.PixelDataLength];
string bitString = "0";
depthFrame.CopyPixelDataTo(bits);
foreach (var bit in bits)
{
bitString += bit.ToString();
Console.Write("This fires.");
}
Console.Write("This never fires and I don't know why.");
Program.Broadcast(bitString); //this also fails to fire.
}
Console.Write("This never fires either.");
}
Looking at the code there's no obvious reason for it not to work. I doubt it has anything to do with the using() block.
Maybe check the following:
Is your foreach loop terminating? How many elements are in the bits array and how many times is "This Fires" being written out?
The console output may be getting buffered and you aren't seeing anything printed until it is flushed. What happens if you replace Console.Write() with Console.WriteLine()?
The only other way execution could be breaking out of the loop without reaching Program.Broadcast(bitString) is if an exception is being thrown. Try wrapping the whole function in a try/catch/finally construct and print any exceptions that occur, and possibly a message in the finally block that should be printed no matter what happens.
Hope that helps.
Maybe the foreach takes too long? try using StringBuilder.
StringBuilder bitString = new StringBuilder("0");
depthFrame.CopyPixelDataTo(bits);
foreach (var bit in bits)
{
sb.Append(bit.ToString();
}
Program.Broadcast(bitString.ToString());
I've noticed this problem happening a lot in most things I do, so I'm thinking there must be a design pattern for this.
Basically if an exception is thrown, attempt to solve the problem and retry. If I place it in the try, all it will do is catch the exception, but I want to retry whatever it was doing and if it fails again, retry again a certain number of times.
Is there a common pattern for this sort of stuff?
check this SO answer.. hope that helps u
Cleanest way to write retry logic?
public static class RetryUtility
{
public static void RetryAction(Action action, int numRetries, int retryTimeout)
{
if(action == null)
throw new ArgumenNullException("action");
do
{
try
{
action();
return;
}
catch
{
if(numRetries <= 0)
throw; // Avoid silent failure
else
{
Thread.Sleep(retryTimeout);
numRetries--;
}
}
}
while(numRetries > 0);
}
}
Call
RetryUtility.RetryAction( () => SomeFunctionThatCanFail(), 3, 1000 );
Credit goes to LBushkin
This runs indefinately but it would be easy to add a loop counter to the while clause
var solved = false;
var tries = 0;
while (!solved)
{
try
{
//Do Something
solved = true;
}
catch
{
//Fix error
}
finally
{
if(solved || IsRediculous(tries))
break;
tries++;
}
}
try/catch inside a loop, with a counter for retries?
EDIT: And your requirement of "retry whatever it was doing," you need custom logic for that, how to retry varies wildly (ie, reopen a stream, recreate the object, pause for X milliseconds, etc...), so you need it's own try/catch inside a loop for every atomic operation.
By "atomic operation" I mean a set of related statements, such as read a file. The whole file read into memory might be an atomic operation, for example.
On some limited basis, you might want to put your try/catch into a loop, and force break if is ultimately successful. Such might be for internet access testing and you want user to have another attempt at connection.
Something like this, maybe:
int MAX_RETRIES = 5;
for (var attempt=1; attempt <= MAX_RETRIES; attempt++) {
try {
DoSomethingThatMightThrow();
}
catch (AnExceptionIKnowHowToHandle) {
if (attempt < MAX_RETRIES)
continue;
throw;
}
}
Depends what you are trying, but typically you want to check for the possibility of an exception happening PRIOR to executing the code that could cause an exception.
For example, check that a file exists before accessing it, and create it (or whatever) if it doesn't.
Are you sure exception handling is the proper methodology here? If you can "solve the problem" you can probably detect the error condition prior to calling the exception-generatiing code.
Exception handling is most natural for things which are truly exceptional. A failed Internet connection (as in the previous answer) is something that can be detected and handled before calling exception-throwing code.
Yes, it is quite common to have a loop with a number of retries where you break out of the loop on success. A couple of things:
You might want to add a delay before retrying so that you don't use up all your retries in just a few milliseconds before the temporary problem had time to fix itself.
If you eventually fail, you should throw the first exception you caught, not the last one. The second exception could be the result of failing to recover correctly from the first failure and might not help to debug the original problem.
Coding what others have already mentioned:
var success = false;
var attempts = 0;
var maxAttempts = 0;
do {
attempts++;
try {
/* your code */
success = condition;
} catch(SuperciliousException e) {
/* recover */
}
} while(!success && attempts < maxAttempts);