Wait until elements style or background picture changes - c#

I would like to improve my wait.Until function to detect if backgroung-image changes on specific element.
Problem is that time to time element change takes more than 10 seconds (Thread.Sleep(10000)).
Increasing Sleep is not option or the solution I want.
Function:
var wait = new WebDriverWait(browser.Driver, new TimeSpan(0, 1, 0));
wait.Until(_ => {
browser.Driver.Navigate().Refresh();
Thread.Sleep(10000);
wait.Until(ExpectedConditions.ElementIsVisible(By.CssSelector("[id='kioskEnabledImg']")));
var tisDriverIndicator = browser.Driver
.FindElement(By.CssSelector("[id='kioskEnabledImg']"));
Assert.True(tisDriverIndicator != null, "Cannot find detector for TIS eSIG driver.");
return tisDriverIndicator.GetCssValue("background-image") != null &&
tisDriverIndicator.GetCssValue("background-image").Contains("mark_enabled.png");
});
I tried to increased to 15s but result was more on less the same (could not detect change).
I tried with other waits (implicit, explicit, ...) but could not improve the current solution.
The change happens and we detect it but i could not find proper way to exit wait function.
Exited after 60s because limit of wait.

Related

c# make my a specific line to timeout after x seconds c#

I have a line in C# which does not work very reliable and does not time out at all and runs for infinity.
to be more precise i am trying to check the connection to a proxy WebClient.DownloadString
I want it to timeout after 5 seconds without making the full method asynchronous
so the code should be like this:
bool success = false
do_this_for_maximum_5_seconds_or_until_we_reach_the_end
{
WebClient.DownloadString("testurl");
success = true;
}
it will try to download testurl and after it did download it it will set success to true. If DownloadString takes more than 5 seconds, the call is canceled, we do not reach the the line where we set success to true, so it remains false and i know that it field.
The thread will remain frozen while we try to DownloadString, so the action is not taking parallel. The ONLY difference to a normal line would be that we set a timeout after 5 seconds
Please do not suggest alternatives such as using HttpClient, because i need a similar codes also for other places, so i simply want a code which will run in a synchronous application (i have not learned anything about asynchronus programing therefore i would like to avoid it completely)
my approach was like suggested by Andrew Arnott in this thread
Asynchronously wait for Task<T> to complete with timeout
however my issue is, I am not exactly sure what type of variable "SomeOperationAsync()" is in his example (i mean it seems like a task, but how can i put actions into the task?), and the bigger issue is that VS wants to switch the complete Method to asynchronos, but i want to run everything synchronous but just with a timeout for a specific line of code.
In case the question has been answered somewhere kindly provide a link
Thank you for any help!!
You should use Microsoft's Reactive Framework (aka Rx) - NuGet System.Reactive and add using System.Reactive.Linq; - then you can do this:
var downloadString =
Observable
.Using(() => new WebClient(), wc => Observable.Start(() => wc.DownloadString("testurl")))
.Select(x => new { success = true, result = x });
var timeout =
Observable
.Timer(TimeSpan.FromSeconds(5.0))
.Select(x => new { success = false, result = (string)null });
var operation = Observable.Amb(downloadString, timeout);
var output = await operation;
if (output.success)
{
Console.WriteLine(output.result);
}
The first observable downloads your string. The second sets up a timeout. The third, uses the Amb operator to get the result from which ever of the two input observables completes first.
Then we can await the third observable to get its value. And then it's a simple task to check what result you got.

Dataflowblock stops updating UI but still runs the action?

This issue is really hard to debug, not always happens (not happen in a short time so that I can just debug the code easily) and looks like no one out there has had the similar issue like this? (I've googled for hours without finding anything related to this issue).
In a short word, my dataflow network works fine at some point until I find out that the terminal block (which updates the UI) seems to stop working (no new data updated on the UI) whereas all the upwards dataflow blocks are still working fine. So it's like there is some disconnection between the other blocks and the ui block here.
Here is my detailed dataflow network, let's check out first before I'm going to explain more about the issue:
//the network graph first
[raw data block]
-> [switching block] -> [data counting block]
-> [processing block] -> [ok result block] -> [completion monitoring]
-> [not ok result block] -> [completion monitoring]
//in the UI code behind where I can consume the network and plug-in some other blocks for updating
//like this:
[ok result block] -> [ok result counting block]
[not ok result block] -> [other ui updating]
The block [ok result block] is a BroadcastBlock which pushes result to the [ok result counting block]. The issue I've described partly here is this [ok result counting block] seems to be disconnected from [ok result block].
var options = new DataflowBlockOptions { EnsureOrdered = false };
var execOptions = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 80 };
//[raw data block]
var rawDataBlock = new BufferBlock<Input>(options);
//[switching block]
var switchingBlock = new TransformManyBlock<Input,Input>(e => new[] {e,null});
//[data counting block]
var dataCountingBlock = new BroadcastBlock<Input>(null);
//[processing block]
var processingBlock = new TransformBlock<Input,int>(async e => {
//call another api to compute the result
var result = await …;
//rollback the input for later processing (some kind of retry)
if(result < 0){
//per my logging, there is only one call dropping
//in this case
Task.Run(rollback);
}
//local function to rollback
async Task rollback(){
await rawDataBlock.SendAsync(e).ConfigureAwait(false);
}
return result;
}, execOptions);
//[ok result block]
var okResultBlock = new BroadcastBlock<int>(null, options);
//[not ok result block]
var notOkResultBlock = new BroadcastBlock<int>(null, options);
//[completion monitoring]
var completionMonitoringBlock = new ActionBlock<int>(e => {
if(rawDataBlock.Completion.IsCompleted && processingBlock.InputCount == 0){
processingBlock.Complete();
}
}, execOptions);
//connect the blocks to build the network
rawDataBlock.LinkTo(switchingBlock);
switchingBlock.LinkTo(processingBlock, e => e != null);
switchingBlock.LinkTo(dataCountingBlock, e => e == null);
processingBlock.LinkTo(okResultBlock, e => e >= 9);
processingBlock.LinkTo(notOkResultBlock, e => e < 9);
okResultBlock.LinkTo(completionMonitoringBlock);
notOkResultBlock.LinkTo(completionMonitoringBlock);
In the UI code behind, I plug in some other UI blocks to update the info. Here I'm using WPF but I think it does not matter here:
var uiBlockOptions = new ExecutionDataflowBlockOptions {
TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
};
dataCountingBlock.LinkTo(new ActionBlock<int>(e => {
//these are properties in the VM class, which is bound to the UI (xaml view)
RawInputCount++;
}, uiBlockOptions));
okResultBlock.LinkTo(new ActionBlock<int>(e => {
//these are properties in the VM class, which is bound to the UI (xaml view)
ProcessedCount++;
OkResultCount++;
}, uiBlockOptions));
notOkResultBlock.LinkTo(new ActionBlock<int>(e => {
//these are properties in the VM class, which is bound to the UI (xaml view)
ProcessedCount++;
PendingCount = processingBlock.InputCount;
}, uiBlockOptions));
I do have code monitoring the completion status of the blocks: rawDataBlock, processingBlock, okResultBlock, notOkResultBlock.
I also have other logging code inside the processingBlock to help diagnosing.
So as I said, after some fairly long time (about 1 hour with about 600K items processed, actually this number says nothing about the issue, it could be random), the network seems to still run fine except that some counts (ok result, not ok result) are not updated, as if the okResultBlock and notOkResultBlock were disconnected from the processingBlock OR they were disconnected from the UI blocks (which updates the UI). I ensure that the processingBlock is still working (no exception logged and the results are still written to file), the dataCountingBlock is still working well (with new count updated on the UI), all the blocks processingBlock, okResultBlock, notOkResultBlock are not completed (their completions are .ContinueWith a task which logs out the status and nothing logged).
So it's really stuck there. I don't have any clue about why it could stop working like that. This could only happen when we use a black-box library like TPL Dataflow. I know it may also be hard for you to diagnose, imagine and think about possibilities. I just asked here for suggestions to solve this as well as any shared experience (about the similar issues) from you and possibly some guesses about what could cause such kind of issue in TPL Dataflow
UPDATE:
I've successfully reproduced the bug one more time and before I had prepared some code to write down some info to help debugging. The issue now keeps down to this point: The processingBlock somehow does not actually push/post/send any msg to all the linked blocks (including the okResultBlock and notOkResultBlock) AND even a new block (prepended with DataflowLinkOptions having Append of false) linked to it could not receive any message (the result). As I said the processBlock does seem to still work fine (its Action does run the code inside and produce result logging normally). So this is still a very strange issue.
In a short word, the problem now becomes why the processBlock could not send/post its messages to all the other linked blocks? Is there any possible cause for that to occur? How to know if the blocks are linked successfully (after the call to .LinkTo)?
It's actually my fault, the processingBlock is actually blocked but it's blocked correctly and in a good way (by design).
The processingBlock is blocked by 2 factors:
The EnsureOrdered is true (as by default), so the output is always queued in the processed order.
There is at least one output result which cannot be pushed out (to some other block).
So if one output result cannot be pushed out, it will be a blocking item because of all the output results being queued in the processed order. All the after processed output results will simply be blocked (queued up) by the first output result that cannot be pushed out.
In my case the special output result that cannot be pushed out here is a null result. That null result can only be produced by some error (exception handling). So I have 2 blocks okResultBlock and notOkResultBlock linked to the processingBlock. But both those blocks are filtered to let only non-null results go through. Sorry that my question does not reflect the exact code I have, about the output type. In the question it is just a simple int but actually it's a class (nullable), the actual linking code looks like this:
processingBlock.LinkTo(okResultBlock, e => e != null && e.Point >= 9);
processingBlock.LinkTo(notOkResultBlock, e => e != null && e.Point < 9);
So the null output result will be blocked and consequentially block all the after processed result (because of the option EnsureOrdered being true by default).
To fix this, I just simply set the EnsureOrdered to false (although this is not required to avoid the blocking, but it's good in my case) and add one more block to consume the null output result (this is the most important to help avoid blocking):
processingBlock.LinkTo(DataflowBlock.NullTarget<Output>(), e => e == null);

Selenium C# Maximum time to wait for Timeout Exception

What is the maximum explicit timeout that Selenium C# waits before it throws timeout exception?
Sometimes the application which we are testing becomes very slow and takes up to 4 mins to load .I want to add a wait time, so that it will wait a maximum upto 5 mins.
I have tried with this code
WebDriverWait wait1 = new WebDriverWait(WebDriver, TimeSpan.FromMinutes(5));
wait1.Until(x => (bool)((IJavaScriptExecutor)x).ExecuteScript("returnjQuery.active==0"));
But it throws timeout exception around 2 mins.
Webdriver has ways for implict and exlict wait but that wont be useful when page is taking too long to load. Also, when an exception or error is occured in the flow, we end up waiting unnecessarily for “specified” time though page has already loaded and nothing is going to change in the remaining time period.
One of the limitation of Webdriver API is no support for WaitForPageLoad out of the box. But we can implement that using WebDriverWait class and readyState property of DOM.
WebDriverWait can wait for element. I afraid that WebDriverWait won't work on JavaScriptExecutor directly. you need to handle something like below
You can wait till document to be in ready state.
string state = string.Empty;
state = ((IJavaScriptExecutor) _driver).ExecuteScript(#"return document.readyState").ToString();
The full code be like below
public void WaitForPageLoad(int maxWaitTimeInSeconds) {
string state = string.Empty;
try {
WebDriverWait wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(maxWaitTimeInSeconds));
//Checks every 500 ms whether predicate returns true if returns exit otherwise keep trying till it returns ture
wait.Until(d = > {
try {
state = ((IJavaScriptExecutor) _driver).ExecuteScript(#"return document.readyState").ToString();
} catch (InvalidOperationException) {
//Ignore
} catch (NoSuchWindowException) {
//when popup is closed, switch to last windows
_driver.SwitchTo().Window(_driver.WindowHandles.Last());
}
//In IE7 there are chances we may get state as loaded instead of complete
return (state.Equals("complete", StringComparison.InvariantCultureIgnoreCase) || state.Equals("loaded", StringComparison.InvariantCultureIgnoreCase));
});
} catch (TimeoutException) {
//sometimes Page remains in Interactive mode and never becomes Complete, then we can still try to access the controls
if (!state.Equals("interactive", StringComparison.InvariantCultureIgnoreCase))
throw;
} catch (NullReferenceException) {
//sometimes Page remains in Interactive mode and never becomes Complete, then we can still try to access the controls
if (!state.Equals("interactive", StringComparison.InvariantCultureIgnoreCase))
throw;
} catch (WebDriverException) {
if (_driver.WindowHandles.Count == 1) {
_driver.SwitchTo().Window(_driver.WindowHandles[0]);
}
state = ((IJavaScriptExecutor) _driver).ExecuteScript(#"return document.readyState").ToString();
if (!(state.Equals("complete", StringComparison.InvariantCultureIgnoreCase) || state.Equals("loaded", StringComparison.InvariantCultureIgnoreCase)))
throw;
}
}
Source :-
https://automationoverflow.wordpress.com/2013/07/27/waiting-for-page-load-to-complete/
Refer below for
How to make Selenium WebDriver wait for page to load when new page is loaded via JS event
Hope it will help you :)
Answering straight if you are using ExplicitWait i.e. WebDriverWait while the page gets loaded through:
WebDriverWait wait1 = new WebDriverWait(WebDriver, TimeSpan.FromMinutes(5));
wait1.Until(x => (bool)((IJavaScriptExecutor)x).ExecuteScript("returnjQuery.active==0"));
IMO, it's a overhead.
It is worth to mention that once your script starts loading an url, by default the browser client returns document.readyState === "complete". Then only your next line of code gets executed.
Page Loading:
Now let me get a bit specific now. Using Selenium, by default 3 (three) types of timeouts are implemented as follows:
session script timeout: Specifies a time to wait for scripts to run. If equal to null then session script timeout will be indefinite. Otherwise it is 30,000 milliseconds.
session page load timeout: Specifies a time to wait for the page loading to complete. Unless stated otherwise it is 300,000 milliseconds. [document.readyState === "complete"]
session implicit wait timeout: Specifies a time to wait in milliseconds for the element location strategy when retreiving elements and when waiting for an element to become interactable when performing element interaction . Unless stated otherwise it is zero milliseconds.
Element Loading:
In case after an interaction with an element (elementA, which calls a jQuery) you need to wait for a jQuery to be completed for another element to be interactable (elementB), the function you mentioned fits the bill.
Conclusion:
As you are looking for a solution to timeout after 5 mins while loading the url, it is already implemented by default through session page load timeout with a value 300,000 milliseconds or 5 minutes.

Keeping console app from closing but still run codes

I have a console app that does not terminate using a code
new System.Threading.AutoResetEvent(false).WaitOne();
What I want to achieve: I would want to run a StopWatch and if it meets a condition it will run certain file manipulating codes. And then finally after the block of code, resets the timer and wait for it to be true again to rerun.
Problem: However, upon debugging I cant get my code to go through my conditions even it has already passed the required condition.
My Code:
static void Main(string[] args)
{
string mutex_id = "41585f436f766572743243494d";
using (System.Threading.Mutex mtx = new System.Threading.Mutex(false, mutex_id))
{
if(!mtx.WaitOne(0,false))
{
return;
}
processTimer = new Stopwatch();
processTimer.Start();
if (processTimer.Elapsed.Seconds > 10)
{
processTimer.Stop();
fileQueue = Directory.GetFiles(ConfigurationManager.AppSettings["WatchPath"], ConfigurationManager.AppSettings["Format"]).ToList();
}
//process the fileQueue
//..
//..
//processTimer.Reset(); -> Reset Timer to wait for another 10 sec and process again
new System.Threading.AutoResetEvent(false).WaitOne();
}
}
I have used a FileSystemWatcher before but I failed to get the process correctly(Like Consecutive/Concurrent file creations and such). Tried Threading and Timers as my question.
Now I'm trying to approach this issue from a new perspective. Hope some can enlighten me with this.
There is no "try again" in your code.
The code you've written does the following:
Create a mutex and lock it
If it already exists, close application
Start a stopwatch
Check if 10 seconds elapsed (which they didn't)
Create a new AutoResetEvent and wait for ever for it
You will need some loop that periodically checks if 10 seconds have passed and otherwise Sleep

Check if process is idling

I'm trying to find out when a process has stopped doing his work. I've been trying it with this code but it doesn't notice that the program is still running and processing a file. Probably because it's still doing things that take less then one microsecond:
TimeSpan startTime = m_Process.TotalProcessorTime;
int idleCycles = 0;
int iMax = Math.Max(iMinNoActivityTime/100, 5);
while (idleCycles < iMax)
{
Sleep(100);
TimeSpan curTime = m_Process.TotalProcessorTime;
int delta = curTime.Subtract(startTime).Milliseconds;
if (delta != 0)
{
idleCycles = 0;
}
else
{
idleCycles++;
}
startTime = curTime;
}
It's called for 3000 seconds: 30 consecutive time-blocks of 100 miliseconds without processor activity.
Is there any way to do this so it doesn't see it as idling when it's still running? The process reads the file, deletes it and then processes it so it can't monitor the directory.
I'd go back and look at your design here. Trying to spot when another process is idle doesn't seem like a very solid approach.
Why not just have the other process use a named event to signal when it is done?
If you know that the work is being done on the main (UI) thread, for example for a simple console application, then you can use Process.WaitForInputIdle. You can optionally specify a timeout parameter if you just want to poll. Now, if the work is being done on a background thread, then you're not going to be able to detect it (at least not without resorting to some nasty hacks). As GrahamS points out, it's certainly better to rethink design in thise case.

Categories