2012-01-12 2 views
4

Я работаю над небольшим приложением на C#, которое обновляет веб-страницу до тех пор, пока не будут выполнены некоторые условия. У меня есть «Огонь» = начать освежающую кнопку и «Стоп!». который должен остановить операцию. Моя проблема состоит в том, что требуется 2 попытки нажать кнопку остановки вместо 1. Ниже мой код:Моя кнопка требует двух кликов вместо одного

Обновленный код с таймером. Тем не менее, я думаю, что может быть лучше использовать таймер, я думаю, что он не обновляется каждую секунду после первых 2-3 обновлений или вообще не обновляется. Есть ли недостаток в моем коде, который я не могу обнаружить?

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; 
} 

}

ответ

3

Вы должны действительно изменить код, чтобы использовать таймер. Когда вы злоупотребляете потоком графического интерфейса пользователя и выполняете периодические вызовы на Application.DoEvents();, клик может обрабатываться только в этом месте, то есть вам нужно ввести цикл для обработки события.

Это абсолютное отсутствие программирования GUI. Вместо этого используйте таймер.

Here является примером того, как таймер может использоваться для периодического вызова метода. В вашем случае выполните обновление страницы.

+0

Я отредактировал мой вопрос с помощью некоторого кода «Таймер». – iCantSeeSharp

+0

Я не уверен на 100%, но я думаю, что страница обновляется до того, как она будет загружена. – iCantSeeSharp

+0

Да, вы правы, переместите вызов на «Обновить» в нижней части метода «RefreshBrowser». Его следует вызывать после 'Navigate' – jdehaan

0

Я предполагаю, что вы застряли в цикле For и не можете остановиться, пока этот цикл не завершится. Вот почему, по-видимому, требуется два клика, и он просто ждет остановки.

Попробуйте вместо этого использовать поток, который выполняет обновление веб-страницы и вызывает thread.run() в вашей кнопке Run Button и thread.stop() в клике Stop. Поскольку обновление веб-страницы будет происходить в отдельном потоке, оно никогда не сможет помешать взаимодействию с пользовательским интерфейсом.

2

Мне кажется, что это происходит из-за того, что вы выполняете все в одном потоке, поэтому, когда ваш код работает, взаимодействие с пользовательским интерфейсом возможно (= первый щелчок), и, хотя страница перезагружает взаимодействие с пользовательским интерфейсом (= вторая нажмите). Если это проблема, выполните свою логику refresch в отдельном потоке.

Что-то вроде:

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(); 
} 

Если доступ к UI-элементы в тему вы также должны использовать Invoke!

+3

Это, на мой взгляд, слишком громоздко для новичков, Таймер лучше подходит, потому что он позволяет напрямую вызывать элементы GUI (он вызывается в графическом интерфейсе) + нужен сон и цикл для выполнения повторной задачи. В основном вам нужно перекодировать таймер :-) – jdehaan

+0

@jdehaan: Я согласен, если вы хотите только вызывать рефрексы каждые x секунд, но я прочитал вопрос и пример, чтобы сделать это непрерывно. Но в любом случае было бы лучше с таймером, потому что он не будет использовать столько ресурсов, и опыт пользователя должен быть примерно таким же ... – ChrFin

Смежные вопросы