How do i pause execution for my CS-Script, How to wait main calling thread.
i have a loop. but second iteration started without completion of the first iteration.
and second csscript executed.
foreach (var website in siteList)
{
try
{
string url = Common.GetWebSearchURL(website.ToUpper());
string webFile = Common.GetWebSearchURL(website.ToUpper() + "_SCRIPT");
CSScript.Evaluator.ReferenceAssembliesFromCode(webFile, true);
ICommon script = CSScript.Evaluator.LoadFile<ICommon>(webFile);
script.Run(ref pnlBroswer, website, url);
}
catch (Exception ex) { }
}
You could also have the script leave some evidence that it completed. It could output a value to a text file, or just create a file, whatever. You call the script, then check for that indicator until you find it (or decide to give up), then continue.
bool CheckFile() { return someFileContainsValue }
try
{
bool completed = false;
executeScript(); // will update a text file when complete
while(!completed)
{
completed = CheckFile();
}
}
Obviously an async version would be cleaner, but the principle is the same.
Related
I'm using WebDriverWait to get the value of a WebElement after some time, but if it doesn't change, I don't want it to fail, just get the current value and keep going with the execution.
I'm running a process in a Web that has a "process completed" label that I use to check if it finished. On the same screen there is an "elapsed time" for the process that I need to read to report how much time it took to run the process.
The issue is that there is a backend process running even after the "process completed" label appeared, and the time gets updated. I can't know how much time this "backend update" will take, and I don't know if in happy runs it can appear before mentioned label, for the moment, from my tests it goes from 10 to 40 seconds (60 to be sure).
We have a Waits class for this kind of stuff, but we didn't have a method for this text change validation, so I came up with this:
private static WebDriverWait _customWait(int value) => new WebDriverWait(
clock,
Driver.Instance,
TimeSpan.FromSeconds(value),
TimeSpan.FromMilliseconds(Settings.Timeouts.SleepIntervalInMillis));
public static void WaitForTextElementToChange(Func<IWebDriver, IWebElement> elementFinder, IWebDriver driver, int time)
{
string oldValue = elementFinder.Invoke(driver).Read();
_customWait(time).Until(drv =>
{
try
{
return !elementFinder.Invoke(driver).Read().Contains(oldValue);
}
catch (NotFoundException)
{
return true;
}
catch (StaleElementReferenceException)
{
return true;
}
});
}
This works. And I remark it because I don't fully understand yet the syntax and logic behind that Until method, I know that it gives a WebDriverTimeoutException and I left it that way to be an additional method for the framework.
So, if the value changes it gets out and keeps running lovely, but in this particular case, if it doesn't change, I don't need it to throw that exception so I called it within a try/catch.
Waits.WaitForProcessToFinish(drv => processCompleteLabel); //<- context code
try
{
//If value changes before 60 secs everything is fine
Waits.WaitForTextElementToChange(drv => timeElement, someDriverObject, 60);
//60 is a hardcoded int value just for testing
}
catch (WebDriverTimeoutException)
{
//But if it doesn't change just do nothing
}
string timeElapsed = timeElement.Read(); //<- context code
My question is, would it be ok to leave it that way?
What would you do instead?
Based on what I see in the source I don't think there is a way around this with how Until works.
The Until method executes a method passed to it in a loop until either a bool or object is returned or the timeout occurs.
public virtual TResult Until<TResult>(Func<T, TResult> condition)
{
if (condition == null)
{
throw new ArgumentNullException("condition", "condition cannot be null");
}
var resultType = typeof(TResult);
if ((resultType.IsValueType && resultType != typeof(bool)) || !typeof(object).IsAssignableFrom(resultType))
{
throw new ArgumentException("Can only wait on an object or boolean response, tried to use type: " + resultType.ToString(), "condition");
}
Exception lastException = null;
var endTime = this.clock.LaterBy(this.timeout);
while (true)
{
try
{
var result = condition(this.input);
if (resultType == typeof(bool))
{
var boolResult = result as bool?;
if (boolResult.HasValue && boolResult.Value)
{
return result;
}
}
else
{
if (result != null)
{
return result;
}
}
}
catch (Exception ex)
{
if (!this.IsIgnoredException(ex))
{
throw;
}
lastException = ex;
}
// Check the timeout after evaluating the function to ensure conditions
// with a zero timeout can succeed.
if (!this.clock.IsNowBefore(endTime))
{
string timeoutMessage = string.Format(CultureInfo.InvariantCulture, "Timed out after {0} seconds", this.timeout.TotalSeconds);
if (!string.IsNullOrEmpty(this.message))
{
timeoutMessage += ": " + this.message;
}
this.ThrowTimeoutException(timeoutMessage, lastException);
}
Thread.Sleep(this.sleepInterval);
}
}
What you're doing works, But I would suggest having your own timeout loop without using Wait.Until() since it's core function is to throw an exception if there is an issue.
I am trying to refresh the page when an element I am trying to find isnt displayed I have written this code but instead of just skipping the if statement the test just fails
while (true)
{
if (Driver.Instance.FindElement(By.LinkText("Leather Utility Vest")).Displayed)
{
var clickButton = Driver.Instance.FindElement(By.LinkText("Leather Utility Vest"));
clickButton.Click();
break;
}
Driver.Instance.Navigate().Refresh();
}
I just used this code instead
while (true)
{
try
{
var clickButton = Driver.Instance.FindElement(By.LinkText("Leather Utility Vest"));
clickButton.Click();
break;
}
catch(Exception)
{
Driver.Instance.Navigate().Refresh();
}
}
This catches the error that the element wasn't found which was why the test was failing and runs the catch block which refreshes the webpage
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.
Looping through a folder using system thread, how to ignore and continue if access to file was denied.
// Start thread.
System.Threading.ThreadStart start = delegate { scanner(#"C:\", "*.html;*.txt"); };
System.Threading.Thread thread = new System.Threading.Thread(start);
thread.Start();
private static string scanstatus = string.Empty;
private static void scanner(string folder, string patterns)
{
try
{
// Get the patterns.
string[] pattern_array = patterns.Split(';');
// Search.
foreach (string pattern in pattern_array)
{
foreach (string path in System.IO.Directory.GetFiles(folder, pattern, System.IO.SearchOption.AllDirectories))
{
// trim path
scanstatus = (path.Length > 60) ? "../" + path.Substring(path.Length - 59, 59) : path;
System.Threading.Thread.Sleep(5000);
}
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
finally
{
Console.WriteLine("*************DONE*************");
}
}
As Daniel mentioned in the comment, basically when you want to keep going with the next iteration, you need to move the try/catch to inside the loop. Currently your catch is outside the outer loop, so if an exception is thrown, execution can't continue. There's no concept of "continue from where you'd got to" within C#.
I'd strongly suggest that you also limit what you catch. For example:
foreach (string pattern in patternArray)
{
try
{
foreach (string path in Directory.GetFiles(...))
{
// ...
}
}
catch (IOException e)
{
// Log it or whatever
}
// Any other exceptions you want to catch?
}
Notes:
Catching Exception is almost always a bad idea, except as a final backstop at the top level of your request (or whatever) handling
Underscores in variable names aren't conventional in .NET; typically you'd use camelCase for variables (and PascalCase for methods, classes etc)
With using directives you can avoid putting the fully-qualified type names in your code, which would make it much easier to read
This method will end up being quite long - I'd suggest extracting the inner loop; possibly including the try/catch, or possibly not.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
C# cleanest way to write retry logic?
i having a function contains web service call to the server which fails sometime (unable to connect remote server error) due to some disturbance in network. The code is in try catch block. i want to rerun the web service call within try block so that the web call will be done successfully.
const int MaxRetries = 5;
for(int i = 0; i < MaxRetries; i++)
{
try
{
// do stuff
break; // jump out of for loop if everything succeeded
}
catch(Exception)
{
Thread.Sleep(100); // optional delay here
}
}
bool success = false;
int retry = 0;
while (!success && retry<3)
{
try{
// web service calls
success = true;
} catch(Exception) {
retry ++;
}
}
public void Connect()
{
Connect(1);
}
private void Connect(int num)
{
if (num > 3)
throw new Exception("Maximum number of attempts reached");
try
{
// do stuff
}
catch
{
Connect(num++);
}
}
You can put a loop around the try catch block like this:
bool repeat = true
while( repeat){
repeat = false;
try
{
...
}
catch( Exception )
{
repeat = true;
}
}
I think you have your answer here. I just wanted to add a couple of suggestions based on my abundant experience with this problem.
If you add logging to the catch block, you can ascertain how often the web service call fails, and how many attempts were made in all. (Maybe put a toggle in web.config to turn this logging off once the issue subsides.)
That information may prove useful in discussions with system administrators if, for example, the web service provider is within your organization, such as on an intranet.
In addition, if you find that the calls are still failing too often, you could introduce a delay in the catch, so that the retry is not immediate. You might only want to do that on the final attempt. Sometimes it is worth the wait for the user, who doesn't want to lose all the data they have just entered.
And finally, depending on the situation, you could add a Retry button to the UI, so that the user could keep trying. The user could choose to wait five minutes for the network problem to clear itself up, and click Retry.
Wrap the try/catch in a while loop. Set a flag on success to exit the while (or just break out). Make sure you have some sort of retry limit so it won't keep going forever.
while (true)
{
try
{
// call webservice
// handle results
break;
}
catch (TemporaryException e)
{
// do any logging you wish
continue;
}
catch (FatalException e)
{
// do any logging you wish
break;
}
}
If you want to limit the retries, change the termination condition on the while loop.
void Method()
{
do
{
try
{
DoStuff();
return;
}
catch (Exception e)
{
// Do Something about exception.
}
}
while (true);
}
If you find yourself wanting to do this frequently in your code, you might consider implementing a reusable class that encapsulates the "re-try when an error is encountered" logic. This way, you can ensure that the behavior is standardized throughout your code base, instead of repeated each time.
There's an excellent example available on Dan Gartner's blog:
public class Retrier<TResult>
{
public TResult Try(Func<TResult> func, int maxRetries)
{
return TryWithDelay(func, maxRetries, 0);
}
public TResult TryWithDelay(Func<TResult> func, int maxRetries, int delayInMilliseconds)
{
TResult returnValue = default(TResult);
int numTries = 0;
bool succeeded = false;
while (numTries < maxRetries)
{
try
{
returnValue = func();
succeeded = true;
}
catch (Exception)
{
//todo: figure out what to do here
}
finally
{
numTries++;
}
if (succeeded)
return returnValue;
System.Threading.Thread.Sleep(delayInMilliseconds);
}
return default(TResult);
}
}
Well, the easiest would be to copy the code to the catch-block, right?
Another approach could look like:
private void YourMethodThatTriesToCallWebService()
{
//Don't catch errors
}
public void TryToCallWebService(int numTries)
{
bool failed = true;
for(int i = 0; i < numTries && failed; i++)
{
try{
YourMethodThatTriesToCallWebService();
failed = false;
}catch{
//do nothing
}
}
}
You should put the entire catch block into a while statement:
while(retryCount < MAX_RETRY && !success)
{
try
{
//do stuff , calling web service
success = true;
}
catch
{
retryCount++
success = false;
}
}