The page has a div that appears randomly, that must be clicked quickly or it disappears. I have a try catch inside a while loop looking for it in case the element is not found, the catch block prevents the program from stopping and iterates again looking for it.
I've set the implicit wait to 0, so the driver does not wait if the button is not found. The while loop can iterate about every 3ms and I changed the FindElement method from XPath to CssSelector, but its still too slow.
The div has no id, name, or class. there is only the tagname div, attribute ng-show and the div text to go by. the program DOES find the div but it misses it alot before finally clicking it, so im guessing the while loop is just iterating too slow.
What other bottleneck am I missing, how do I make this iterate as fast as possible?
private static void FindButtonAndClick()
{
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(0);
try
{
while (pageStatusOnline == true)
{
if (programStopped == true) { return; };
try
{
driver.FindElement(By.CssSelector("div[ng-show='!buttonClicked']")).Click();
pageStatusOnline = false;
buttonClickedAt = "Page1";
break;
} catch { };
};
}
catch
{
Console.WriteLine("Error during FindButtonAndClick()");
programStopped = true;
};
}
Edit: I did some execution time testing and the above code executes in between 11ms-36ms, I'm guessing the fluctuation is because of the flood of exceptions @Dai mentioned.
@Dai mentions that Events are better so Here is my attempt at using Selenium C# Explicit wait on a separate thread:
bool checkingForButton;
bool programStopped;
string buttonPath = "By.CssSelector(div[ng-show='!buttonClicked'])";
private static void FindButtonAndClick()
{
try
{
driverPage.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(0);
CancellationTokenSource closeThreadSource = new CancellationTokenSource();
CancellationToken token = closeThreadSource.Token;
Thread buttonWaitThread = new Thread(() => WaitForButton(token));
buttonWaitThread.IsBackground = true;
buttonWaitThread.Start();
checkingForButton = true;
while (checkingForButton == true)
{
//WaitForButton on the other thread
//will flip checkingForButton
//when the button is clicked
//and this while loop will end
};
closeThreadSource.Cancel();
buttonWaitThread.Join();
closeThreadSource.Dispose();
}
catch (Exception ex)
{
Console.WriteLine($"Error during FindButtonAndClick(): {ex}");
};
}
private static void WaitForButton(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
if (programStopped == true) { return; };
WebDriverWait pageWait = new WebDriverWait(driverPage, TimeSpan.FromHours(1));
pageWait.PollingInterval = TimeSpan.FromMilliseconds(0);
pageWait.IgnoreExceptionTypes(typeof(NoSuchElementException), typeof(StaleElementReferenceException));
pageWait.Until(ExpectedConditions.ElementToBeClickable(buttonPath))
driverPage.FindElement(buttonPath).Click();
checkingForButton = false;
}
}
next step is using System.Diagnostics.StopWatch() to see if waiting for the event instead of hammering the page is in fact faster. Also looking into the MutationObserver
alternative.