简体   繁体   English

c#WebBrowser DocumentText只能工作一次但不能循环吗?

[英]c# WebBrowser DocumentText works once but not in a loop?

I am interested in checking the content of a website, the content changes frequently and when I view the website on any browser, it refreshes itself every 30 seconds. 我对检查网站的内容感兴趣,该内容经常更改,并且在任何浏览器上查看网站时,它每30秒刷新一次。 I want to know when the content has changed. 我想知道内容何时更改。

I am using winforms and I want to just click a button to start a loop, every 30 seconds. 我正在使用winforms,我想每30秒单击一个按钮即可开始循环。 I don't want to hit the website too frequently, in fact the web pages own refresh is more than enough for my needs. 我不想太频繁地访问该网站,实际上刷新网页本身已足以满足我的需求。

My code works when I click a button (btnCheckWebsite), if I wait a minute and then click btnCheckWebsite again, my message box pops up because the web page has changed. 当我单击一个按钮(btnCheckWebsite)时,我的代码起作用了,如果我等一会儿,然后再次单击btnCheckWebsite,则会弹出我的消息框,因为网页已更改。 This is great however I want to do this in a while loop. 这很棒,但是我想在while循环中这样做。 When I un-comment my while loop, the DocumentText never changes. 当我取消对while循环的注释时,DocumentText永远不会更改。 I have debugged it and for some reason it's the same text every time, even when the web page has changed in the real world, it stays the same in my code. 我已经对其进行了调试,并且由于某种原因,每次它都是相同的文本,即使网页在现实世界中发生了变化,它在我的代码中也保持不变。

So my question is why can't I use a loop and what can I do instead to run this repeatedly without any input from me? 所以我的问题是为什么我不能使用循环,我该怎么做才能在没有任何输入的情况下重复运行该循环?

As a bonus, I would like to remove the .Refresh() I added this because it won't work without it however as I understand it, this refreshes the whole page. 另外,我想删除添加的.Refresh(),因为没有它,它将无法工作,但是据我了解,这会刷新整个页面。 When I use a browser I see the page updating even when I don't refresh the whole page. 使用浏览器时,即使不刷新整个页面,页面也会更新。

Just for background info, I did start by having a WebBrowser control on my form, the page refreshes automatically. 仅出于背景信息的目的,我确实在窗体上安装了WebBrowser控件,页面会自动刷新。 I used the same code and have the same problem, interestingly, the WebBrowser control on my windows form refreshes by itself no problem, until I click btnCheckWebsite and then it stops refreshing! 我使用了相同的代码,并遇到了相同的问题,有趣的是,我的Windows窗体上的WebBrowser控件本身可以自动刷新,直到单击btnCheckWebsite,然后它停止刷新! Also I know about webrequest but I don't know how to use it for my purposes. 我也了解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;

        }
    }
}

You'd need to do your processing upon DocumentCompleted event. 您需要对DocumentCompleted事件进行处理。 This event is asynchronous, so if you want to do this in a loop, the execution thread must pump messages for this event to fire. 此事件是异步的,因此,如果要循环执行此操作,执行线程必须泵送消息以触发此事件。 In a WinFroms app, your UI thread is already pumping messages in Applicaiton.Run , and the only other endorsed way to enter nested message loop on the same thread is via a modal form (here's how it can be done , see in the comments). 在WinFroms的应用程序,你的UI线程已经抽中的消息Applicaiton.Run ,唯一的其他认可的方式在同一个线程进入嵌套的消息循环是通过一个模式窗体(这里是如何是可以做到的 ,看到评论) 。 Another (IMO, better) way of doing such Navigate / DocumentCompleted logic without a nested message loop is by using async/await , here's how . 在没有嵌套消息循环的情况下进行此类Navigate / DocumentCompleted逻辑的另一种(更好的IMO)方法是使用async / await这是方法 In the classic sense, this is not exactly a loop, but conceptually and syntactically it might be exactly what you're looking for. 从经典意义上讲,这并非完全是一个循环,但从概念和语法上讲,这可能正是您要查找的内容。

You can catch the WebBrowser.Navigated Event to get notified when the page was reloaded. 您可以捕获WebBrowser.Navigated事件以在重新加载页面时得到通知。 So you wouldn't need a loop for that. 因此,您不需要为此循环。 (I meant the ready loop) (我的意思是准备循环)

Just navigate every 30 seconds to the page in a loop and in the Navigated Event you can check whether the site has changed or not. 只需每30秒循环浏览一次页面,然后在“导航事件”中可以检查网站是否已更改。

您最好连接DocumentCompleted事件以检查其DocumentText属性!

The WebBrowser Element is very buggy and has much overhead for your needs. WebBrowser元素非常容易出错,并且需要大量开销。 Instead of that you should use WebRequest. 相反,您应该使用WebRequest。 Because you said you don't know how to use, here's an (working) example for you. 因为您说过不知道如何使用,所以这里有一个适合您的示例。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM