c#WebBrowser DocumentText只工作一次,但不能循环使用
本文关键字:一次 但不能 循环 DocumentText 工作 c#WebBrowser | 更新日期: 2023-09-27 18:28:38
我有兴趣检查网站的内容,内容经常更改,当我在任何浏览器上查看网站时,它每30秒刷新一次。我想知道内容什么时候改变了。
我正在使用winforms,我只想每30秒点击一个按钮开始一个循环。我不想太频繁地访问网站,事实上,网页本身的刷新已经足够满足我的需求了。
当我点击一个按钮(btnCheckWebsite)时,我的代码就工作了,如果我等一分钟,然后再次点击btnCheckWebsite,我的消息框就会弹出,因为网页已经更改。这太棒了,不过我想在一段时间内做这件事。当我取消对while循环的注释时,DocumentText永远不会更改。我调试过它,由于某种原因,它每次都是相同的文本,即使网页在现实世界中发生了变化,它在我的代码中也保持不变。
所以我的问题是,为什么我不能使用循环,我该怎么做才能在没有任何输入的情况下重复运行它?
作为奖励,我想删除我添加的.Refresh(),因为没有它它它就无法工作。然而,据我所知,这会刷新整个页面。当我使用浏览器时,即使不刷新整个页面,我也会看到页面在更新。
只是为了了解背景信息,我确实在表单上添加了WebBrowser控件,页面会自动刷新。我使用了相同的代码,也遇到了相同的问题,有趣的是,我的windows窗体上的WebBrowser控件本身刷新没有问题,直到我单击btnCheckWebsite,然后它停止刷新!我也知道webrequest,但我不知道如何将其用于我的目的。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Check_Website
{
public partial class Form1 : Form
{
public WebBrowser _memoryWebBrowser = new WebBrowser();
String _previousSource = "emptySource";
public Form1()
{
InitializeComponent();
_memoryWebBrowser.Navigate(new Uri("http://www.randomurl.com/"));
}
private void btnCheckWebsite_Click(object sender, EventArgs e)
{
//I want to un-comment this while loop and let my code run itself but it stops working
//when I introduce my while loop.
//while (1 < 2 )
//{
//Thread.Sleep(30000);
checkWebsite();
//}
}
private void checkWebsite()
{
//Why do I need this refresh? I would rather not have to hit the web page with a refresh.
//When I view the webpage it refreshed with new data however when I use a WebBrowser
//the refresh just doesn't happen unless I call Refresh.
_memoryWebBrowser.Refresh();
Thread.Sleep(500);
while (((_memoryWebBrowser.ReadyState != WebBrowserReadyState.Complete) || (_memoryWebBrowser.DocumentText.Length < 3000)))
{
Thread.Sleep(1000);
}
String source = _memoryWebBrowser.DocumentText;
if ((source != _previousSource) && (_previousSource != "emptySource"))
{
//Hey take a look at the interesting new stuff on this web page!!
MessageBox.Show("Great news, there's new stuff on this web page www.randomurl.co.uk!!" );
}
_previousSource = source;
}
}
}
您需要对DocumentCompleted事件进行处理。此事件是异步的,因此如果要在循环中执行此操作,则执行线程必须为该事件激发消息。在WinFroms应用程序中,您的UI线程已经在Applicaiton.Run
中发送消息,在同一线程上输入嵌套消息循环的唯一其他认可方式是通过模态形式(以下是如何实现的,请参阅注释)。另一种(IMO,更好)在没有嵌套消息循环的情况下实现Navigate
/DocumentCompleted
逻辑的方法是使用async/await,方法如下。从经典意义上讲,这并不完全是一个循环,但从概念和语法上讲,它可能正是你想要的。
您可以捕获WebBrowser.Navigated事件,以便在重新加载页面时得到通知。所以你不需要一个循环。(我指的是准备好的循环)
只需每隔30秒循环导航到页面,在导航事件中,您可以检查网站是否已更改。
您最好挂接DocumentCompleted事件以检查其DocumentText属性!
WebBrowser元素非常有缺陷,并且有很多开销来满足您的需求。相反,您应该使用WebRequest。因为你说你不知道如何使用,这里有一个(有效的)例子给你。
using System;
using System.Windows.Forms;
using System.Net;
using System.IO;
namespace Check_Website
{
public partial class Form1 : Form
{
String _previousSource = string.Empty;
System.Windows.Forms.Timer timer;
private System.Windows.Forms.CheckBox cbCheckWebsite;
private System.Windows.Forms.TextBox tbOutput;
public Form1()
{
InitializeComponent();
this.cbCheckWebsite = new System.Windows.Forms.CheckBox();
this.tbOutput = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// cbCheckWebsite
//
this.cbCheckWebsite.AutoSize = true;
this.cbCheckWebsite.Location = new System.Drawing.Point(12, 12);
this.cbCheckWebsite.Name = "cbCheckWebsite";
this.cbCheckWebsite.Size = new System.Drawing.Size(80, 17);
this.cbCheckWebsite.TabIndex = 0;
this.cbCheckWebsite.Text = "checkBox1";
this.cbCheckWebsite.UseVisualStyleBackColor = true;
//
// tbOutput
//
this.tbOutput.Location = new System.Drawing.Point(12, 35);
this.tbOutput.Multiline = true;
this.tbOutput.Name = "tbOutput";
this.tbOutput.Size = new System.Drawing.Size(260, 215);
this.tbOutput.TabIndex = 1;
//
// Form1
//
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.tbOutput);
this.Controls.Add(this.cbCheckWebsite);
this.Name = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
this.PerformLayout();
timer = new System.Windows.Forms.Timer();
timer.Interval = 30000;
timer.Tick += timer_Tick;
}
private void Form1_Load(object sender, EventArgs e)
{
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
if (!cbCheckWebsite.Checked) return;
WebRequest request = WebRequest.Create("http://localhost/check_website.html");
request.Method = "GET";
WebResponse response = request.GetResponse();
string newContent;
using (var sr = new StreamReader(response.GetResponseStream()))
{
newContent = sr.ReadToEnd();
}
tbOutput.Text += newContent + "'r'n";
if (_previousSource == string.Empty)
{
tbOutput.Text += "Nah. It's empty";
}
else if (_previousSource == newContent)
{
tbOutput.Text += "Nah. Equals the old content";
}
else
{
tbOutput.Text += "Oh great. Something happened";
}
_previousSource = newContent;
}
}
}