Sharki
Sharki

Reputation: 424

C# Show another form in a loop

So I'm trying to do a program which shows an alert for every number that called. I'm doing webscraping to my router in order to obtain the numbers which are called. The thing is;

while (true)
{
   Thread.Sleep(5000);
   if (!numbers.SequenceEqual(getNumber()))
   {
     numbers = getNumber();

     alert alert = new alert();
     alert.setAlert(numbers.First());
     //break;
   }
}

I'm using a while which is constantly every 5sec check if someone called. And because of that when I show the alert (which is just another form) it doesn't show properly. I just did the test using break, and it works so that's why I assumed it's because the loop. I know little to nothing about async method, and I think this could be a solution...?

Thanks and sorry for my bad english!

Update with the whole code;

Form1.Shown


private void Form1_Shown(object sender, EventArgs e)
{
   ChromeDriverService service = ChromeDriverService.CreateDefaultService();
   service.HideCommandPromptWindow = true;

   ChromeOptions options = new ChromeOptions();
   options.AddArgument("headless");

   ChromeDriver driver = new ChromeDriver(service, options);
   driver.Navigate().GoToUrl("http://192.168.0.1/");

   var user = driver.FindElementByName("loginUsername");
   var pass = driver.FindElementByName("loginPassword");
   var submit = driver.FindElementByClassName("Login-button");

   user.SendKeys("blablabla");
   pass.SendKeys("blablabla");
   submit.Click();

   List<string> getNumber()
   {
        driver.Navigate().GoToUrl("http://192.168.0.1/CallLog.asp");

        var botonPerdidas = driver.FindElementByCssSelector("li[class='TabbedPanelsTab kR']");
        botonPerdidas.Click();

        List<string> strNumbers = new List<string>();
        for (int i = 2; i < 20; i++)
        {
          try
          {
             strNumbers.Add(driver.FindElementByXPath("/html/body/form/div/div[2]/div[2]/div/div[1]/div[1]/div/div[4]/div/div[" + i + "]/div[4]").Text);
          }
          catch (Exception)
          {
             break;
          }
        }
         return strNumbers;
   }


   List<string> numbers = getNumber();

   while (true)
   {
      Thread.Sleep(5000);
      if (!numbers.SequenceEqual(getNumber()))
      {
         numbers = getNumber();

         alert alert = new alert();
         alert.setAlert(numbers.First());
      }
   }

}

The follow method is in the alert form, which is invoked from form1 in the loop for every time I detect a new call.

Alert.setAlert


public void setAlert(string msg)
{

    this.Text = msg;
    this.Opacity = 0.0;
    this.StartPosition = FormStartPosition.Manual;
    string fname;

    for (int i = 1; i <= 10; i++)
    {
       fname = "alert" + i.ToString();
       alert f = (alert)Application.OpenForms[fname];

       if (f == null)
       {
         this.Name = fname;
         this.x = Screen.PrimaryScreen.WorkingArea.Width - this.Width + 15;
         this.y = Screen.PrimaryScreen.WorkingArea.Height - this.Height * i - 5 * i;
         this.Location = new Point(this.x, this.y);
         break;
       }

    }

        this.x = Screen.PrimaryScreen.WorkingArea.Width - base.Width - 5;
        this.label1.Text = msg;
        this.Show();
}

Trying to move it out from the form level.

enter image description here

ErrorMessage: It doesn't exist in the current context.

Upvotes: 1

Views: 191

Answers (1)

JonasH
JonasH

Reputation: 36341

The problem is probably due to the following rules in windows forms:

  1. You shall not block the UI(main) thread with long running operations
  2. You shall only update ui elements from the UI thread

Running an infinite loop in the Show() event breaks rule #1 and will cause issues.

Make your driver a field in the form an instantiate this in the constructor (or show event if needed) and create a regular timer that executes ever 5s:

ChromeDriverService service;
Timer myTimer;
public Form1(){
    InitializeComponent() 
    service = ChromeDriverService.CreateDefaultService();
    ...
    myTimer = new Timer();
    myTimer.Tick += TimerEventProcessor; 
    myTimer.Interval = 5000;
    myTimer.Start();
    ...
}

Create the event handler method to handle the event:

private TimerEventProcessor(Object myObject, EventArgs myEventArgs) {
   
  if (!numbers.SequenceEqual(getNumber()))
  {
     numbers = getNumber();
     alert alert = new alert();
     alert.setAlert(numbers.First());
  }
}
    

Upvotes: 2

Related Questions