Search code examples
c#seleniumrecursionstack-overflow

c# How to handle Stackoverflow exception in recursive function


Hi I am making my web scraping tool, and I need to have a recursive function in milliseconds to view offer availability. But I can't handle the stackoverflow exception because i keep calling the viewoffers() function. Please help :)

public void viewoffers(IWebDriver driver, string user, string pass)
    {
            Thread.Sleep(timespan);

            try { int c = driver.WindowHandles.Count; }
            catch { AbortThread(user); }

            driver.Navigate().GoToUrl("https://as.realtrans.com/webtop/orders/offers/offer_order_viewInfo.asp?user=" + user);

            try { int c = driver.WindowHandles.Count; }
            catch { AbortThread(user); }

            if (driver.Url.ToString().Contains("offer_order_viewInfo.asp?user="))
            {

                try { int c = driver.WindowHandles.Count; }
                catch { AbortThread(user); }

                if (driver.PageSource.Contains("id=\"chkOffer\""))
                {
                    driver.FindElement(By.Id("chkOffer")).Click();
                    driver.FindElement(By.ClassName("CellClass")).FindElement(By.TagName("a")).Click();
                    driver.FindElement(By.Name("btnSubmit")).Click();
                }


                this.viewoffers(driver, user, pass);

            }
            else
            {
                this.reopenaccount(driver, user, pass);

            }
    }


    public void AbortThread(string username)
    {
        RunningAccounts ra = runningAccounts.Find(item => item.account.username == username);
        runningAccounts.Remove(ra);
        threadsList.Remove(ra.thread);
        ra.thread.Abort();

    }

And it will just stop if I make close of the running thread in my program.


Solution

  • Alas, recursion and the stack. The solution here, unfortunately, is to write your code in such a way that doesn't use recursion. Remember that recursion is never required. As a general rule of computer science, if you can write it with recursion, you can write it with a loop. It's nothing more than a shortcut, albeit a really nice shortcut to have (up until it overflows). But if you do it in a loop, that should handle all your problems and be way lighter on resources.

    I obviously haven't tested this, and it's using a while (true) which I generally consider bad practice, but here's an example that should show the theory behind this conversion:

    public void viewoffers(IWebDriver driver, string user, string pass)
    {
        while (true)
        {
            Thread.Sleep(timespan);
    
            try { int c = driver.WindowHandles.Count; }
            catch { AbortThread(user); }
    
            driver.Navigate().GoToUrl("https://as.realtrans.com/webtop/orders/offers/offer_order_viewInfo.asp?user=" + user);
    
            try { int c = driver.WindowHandles.Count; }
            catch { AbortThread(user); }
    
            if (driver.Url.ToString().Contains("offer_order_viewInfo.asp?user="))
            {
                try { int c = driver.WindowHandles.Count; }
                catch { AbortThread(user); }
    
                if (driver.PageSource.Contains("id=\"chkOffer\""))
                {
                    driver.FindElement(By.Id("chkOffer")).Click();
                    driver.FindElement(By.ClassName("CellClass")).FindElement(By.TagName("a")).Click();
                    driver.FindElement(By.Name("btnSubmit")).Click();
                }
            }
            else
            {
                break;
            }
        }
    
        this.reopenaccount(driver, user, pass);
    }
    

    }