iCantSeeSharp
iCantSeeSharp

Reputation: 3880

My button needs two clicks instead of one

I am working on a small app in C# that refreshes a web page until some conditions are met. I have a "Fire" = start refreshing button and a "Stop!" button that is supposed to stop the operation. My problem is that it takes 2 tries to click the stop button instead of 1. Below is my code:

Updated code with timer. Still I think there can be some better use of the timer, I think that it doesn't update every second after the first 2-3 refreshes or doesn't refresh at all. Is there any flaw in my code that I can't detect?

private void FireButtonClick(object sender, EventArgs e)
{

    try
    {
        if (webBrowser1.Url.ToString().StartsWith("some url"))
        {
            _stopped = false;
            _timer.Tick += new EventHandler(RefreshBrowser);
            _timer.Interval = (1000) * (1);
            _timer.Enabled = true;
            _timer.Start();
       }
        else
        {
            MessageBox.Show("You must logon first.");
            return;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

private void RefreshBrowser(object sender, EventArgs e)
{
    string content = "disabled";
    string baseUrl = @"http://some url";
    string newUrl = string.Empty;
    string buttonXpath = @"/html/body/div/div[6]/table/tr/td[2]/table/tr/td/table/tr/td/table/tr[3]/td[2]/div[4]/a";
    webBrowser1.Refresh();
    _proceed = false;
    if (!content.ToLower().Equals("disabled") && !_stopped)
    {

        if (!_stopped)
        {
            HtmlAgilityPack.HtmlDocument htmlDocument = new HtmlAgilityPack.HtmlDocument();
            htmlDocument.LoadHtml(webBrowser1.DocumentText);
            HtmlNode node = htmlDocument.DocumentNode.SelectSingleNode(buttonXpath);
            content = node.GetAttributeValue("disabled", string.Empty);
            newUrl = node.GetAttributeValue("href", string.Empty);
        }
    }
    else
    {

        webBrowser1.Navigate(baseUrl + newUrl);
    }


}

private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
    _proceed = true;
    urlTextBox.Text = webBrowser1.Url.ToString();
}

private void MainPageButtonClick(object sender, EventArgs e)
{
    try
    {
        webBrowser1.Navigate(_mainPage);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

private void GoButtonClick(object sender, EventArgs e)
{
    try
    {
        webBrowser1.Navigate(urlTextBox.Text);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }

}

private void StopButtonClick(object sender, EventArgs e)
{
    _timer.Stop();
    _proceed = true;
    _stopped = true;
}

}

Upvotes: 4

Views: 821

Answers (3)

Christoph Fink
Christoph Fink

Reputation: 23113

It seems to me that this is because you are executing everything in the same thread, so when your code is running no UI interaction is possible (=first click) and while the page is reloading UI interaction is possible (=second click). If that is the problem execute your refresch logic in a seperate thread.

Something like:

private void FireButtonClick(object sender, EventArgs e)
{
    Thread worker = new Thread(new ThreadStart(delegate()
    {
        //your code
    });
    worker.IsBackground = true; //so it does not block the app from being closed
    worker.Start();
}

If you access UI-Elements in the Thread you also need to use Invoke!

Upvotes: 2

Michael Allen
Michael Allen

Reputation: 5838

My guess would be that you are stuck in a For loop and cannot stop until that loop completes. This is why it seems to be needing two clicks, infact it is just waiting to stop.

Try instead using a thread that performs the webpage refreshing and calling thread.run() in your Run Button click and thread.stop() in your Stop button click. Since the webpage refreshing will occur in a separate thread it can never interfere with your UI interaction.

Upvotes: 0

jdehaan
jdehaan

Reputation: 19938

You should really modify your code to use a timer. When you misuse the GUI thread and make periodic calls to Application.DoEvents(); the click can only handled at that place meaning you have to enter the loop to process the event.

This is an absolute no go for GUI programming. Use a timer instead.

Here is an example on how a timer can be used to periodically call a method. In your case to perform the refresh of the page.

Upvotes: 3

Related Questions