C # - How can I block method return for some time interval?

I have a win forms application that contains a web browser control. I need to add a delay between operations in a web browser due to the asynchronous nature of navigation.

The Document_Complete event is useless since it does not take into account that a page can contain multiple AJAX requests. The event is triggered many times.

UPDATE

AJAX requests are executed when the page loads. Thus, page loading and content in any DIV are retrieved using an HTTP request. Thus, the Document_Complete event occurs when the document is loaded first, and then each HTTP request (AJAX) is returned. No Bueno.

UPDATE2

My application is trying to read HtmlElements from a Webbrowser.Document object. Because the code runs faster than the HTTP requests are returned ... the document object does not contain all the html elements.

I need some way to defer method calls in the main thread. I tried using a timer:

private void startTimer() { timer.Interval = 2000; timer.Start(); while (!BrowserIsReady) { //Wait for timer } } 

This blocks the thread, and the tick event never fires. These loops never end.

I want to run a number of such methods:

 Navagate("http://someurl.com"); //delay ClickALink(); //delay Navagate("Http://somewhere.com"); //delay 

Is it possible to solve this problem with a timer and BackgroundWorker? Can anyone suggest a possible solution?

+4
source share
6 answers

Thanks for all the suggestions. This is the Delay solution that I came up with last night. It seems like using a steam roller to crack peanuts, but I could not find a more โ€œelegantโ€ answer to this particular problem.

I unscrew a new worker thread that calls a method called "AddDelay". This method will cause the worker thread to sleep for a period of time. My main (UI) loop thread is in Thread.IsAlive state, allowing the application to receive OS messages if the thread is not completed.

This seems like a trick.

  private void Delay() { DelayTimer dt = new DelayTimer(1); Thread thread = new Thread(new ThreadStart(dt.AddDelay)); thread.Start(); while (thread.IsAlive) { Application.DoEvents(); } } public class DelayTimer { private int _seconds; public DelayTimer(int time) { _seconds = time; } public void AddDelay() { Thread.Sleep(_seconds*1000); } } 
0
source

You might want to switch to the Monitor class in the Threading namespace. An example is below.

 using System; using System.Threading; namespace MonitorWait { class Program { private static readonly object somelock = new object(); static void Main(string[] args) { ThreadPool.QueueUserWorkItem(new WaitCallback(SyncCall)); Thread.Sleep(5000); //Give the SyncCall a chance to run... //Thread.Sleep(6000); //Uncomment to see it timeout. lock (somelock) { Monitor.Pulse(somelock); //Tell the SyncCall it can wake up... } Thread.Sleep(1000); //Pause the main thread so the other thread //prints before this one :) Console.WriteLine("Press the any key..."); Console.ReadKey(); } private static void SyncCall(object o) { lock (somelock) { Console.WriteLine("Waiting with a 10 second timeout..."); bool ret = Monitor.Wait(somelock, 10000); if (ret) { Console.WriteLine("Pulsed..."); } else { Console.WriteLine("Timed out..."); } } } } } 
+1
source

Unfortunately, you need to call Application.DoEvents() to prevent the browser from working. In addition, I also pay attention to the ReadyState property.

  while (BusyNavigating || (wbBrowser.ReadyState != WebBrowserReadyState.Complete)) { Application.DoEvents(); } 
0
source

Document_Complete tells you when the page has finished loading.

AJAX just lets it load something else. Some WebApplications (e.g. StackOveflow) have timer AJAX calls, which means your application will never load completely because there is always an AJAX call waiting to be executed / returned.

This is a problem because an AJAX function callback might just start another AJAX function. Without parsing the entire page (creating a runtime tree), in fact, you will not be able to determine when the page is really and fully loaded.

Perhaps you could clearly indicate what exactly you need for the application that needs to wait for all AJAX calls to complete and why the expectations for Document_Complete are not good enough.

0
source

I think one of the problems that you might have (I canโ€™t say because the code is incomplete) is that you are trying to do something on your control when invoke is required.

I have encoded a small form that changes the URL every five seconds. Remember that interrogating the state of the web browser in the background thread is also not allowed.

  public partial class Form1 : Form { System.Timers.Timer t = new System.Timers.Timer(); Stack<string> urls = new Stack<string>(); public Form1() { InitializeComponent(); urls.Push("http://stackoverflow.com/"); urls.Push("http://msdn.microsoft.com/"); urls.Push("http://maps.google.com"); t.AutoReset = false; t.Interval = 5000; t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed); } void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (urls.Count > 0 ) { string url = urls.Pop(); SetUrl(url); } t.Interval = 5000; t.Start(); } static void SynchronizedInvoke(ISynchronizeInvoke sync, Action action) { // If the invoke is not required, then invoke here and get out. if (!sync.InvokeRequired) { // Execute action. action(); // Get out. return; } // Marshal to the required thread. sync.Invoke(action, new object[] { }); } private void SetUrl(string url) { SynchronizedInvoke(webBrowser1, () => webBrowser1.Navigate(url)); } private void button1_Click(object sender, EventArgs e) { t.Interval = 1; t.Start(); } } 
0
source

Can't you just use:

  System.Threading.Thread.Sleep(1000); 

Should this have the same effect?

0
source

All Articles