C#多執行緒webbrowser及InvokeMember(“click”)無響應的問題

來源:互聯網
上載者:User

文章重點:多執行緒webbrowser的相關問題,並解決觸發click事件,js無響應問題

最近剛好碰上一個需求:迴圈遍曆網頁元素,找到innerText為指定的內容時,就類比人工點擊

解決辦法:使用WebBrowser將指定位置的文檔載入到 WebBrowser 控制項中(註:這裡的webbrowser是在拉控制項的方式,而不是直接在代碼中new)

源碼如下:

private void loadPage(object URL)        {            try            {                string url = (string)URL;                               browser.Navigate(url);                                while (true)                {                   Application.DoEvents();                                   if(browser.ReadyState != WebBrowserReadyState.Complete)                   {                        break;                   }                }                                                HtmlDocument document = browser.Document;                HtmlElementCollection elems = browser.Document.GetElementsByTagName("a");                foreach (HtmlElement em in elems)                {                    if (em.InnerText == "測試")                    {                                  em.InvokeMember("click");//"觸發點擊事件"                    }                }            }            catch (Exception ex)            {                MessageBox.Show(ex.Message);            }        }      

有一點沒說到,上面的只適合單線程的,如果執行以上代碼的是在新開闢的一個線程中的話,會碰到一系列的問題......(很遺憾,我沒有將那些問題記錄下來,但相信如果你跟我有著同樣的需求的話,即採用多線程的方式處理webbrowser載入的網頁內容的話,可以繼續看下去,也許對你有所協助)

網上一搜,關於webbrowser在多線程中的使用著實會碰到很多問題……後來,經過自己不斷的Google(在這過程中你能體會到百度離Google還有多遠),有找到了幾篇對我有所協助的文章:

關於線程的知識:http://www.cnblogs.com/JimmyZheng/archive/2012/06/10/2543143.html

WebBrowser多線程帶來的麻煩:http://www.cnblogs.com/xjfhnsd/archive/2010/03/14/1685441.html

WebBrowser 顯示Html內容3點細節技巧: http://www.cnblogs.com/cyq1162/archive/2012/03/27/2419655.html

 

接著,我就使用webclient配合webbrowser從而順利的解決了問題。

WebClient:下載指定網址的源碼

WebBrowser:navigate一個空白頁(具體參考:)

註:這裡的WebBrowser要從代碼中new,如果是拉控制項的方式建立的,將會報錯:"指定的轉換無效"

這裡我就寫一個以上列出的文章所沒有提到的。

比如,我們要click的網頁元素是通過js來觸發的,而使用webclient只能下載指定的url的網頁源碼,無法自動載入相關的js,因此導致在使用invokeMember("click")的時候,沒能見到預期效果。

解決辦法:將指定的js檔案也下載下來(或者將需要用到的js方法放到本地,使用webclient  載入進來也行)

我這裡說的只是一個大題的思路和解決途徑

最後,貼上一段測試代碼:

C#源碼:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.Threading;using System.Net;namespace webbrowser控制項{    public partial class Form1 : Form    {        public Form1()        {            InitializeComponent();        }        private void button1_Click(object sender, EventArgs e)        {            Control.CheckForIllegalCrossThreadCalls = false;            ParameterizedThreadStart pt;            pt = new ParameterizedThreadStart(loadPage);            Thread td = new Thread(pt);            td.Name = "主線程";            td.SetApartmentState(ApartmentState.STA);//線上程啟動前設定其單元狀態            td.Start("http://127.0.0.1/test.html");                    }        private void loadPage(object URL)        {            try            {                string url = (string)URL;                WebBrowser browser = new WebBrowser();//當前線程不在單一執行緒 Apartment中,因此無法執行個體化 ActiveX 控制項                browser.ScriptErrorsSuppressed = true;                //browser.Navigate(url);                //browser.DocumentCompleted += browser_DocumentCompleted;                browser.Navigate("about:blank");                string htmlcode = GetHtmlSource(url);                string js = GetHtmlSource("http://127.0.0.1/MY/test/js.html");//載入js                browser.Document.Write(js);                  textBox1.Text = htmlcode;                //while (browser.ReadyState != WebBrowserReadyState.Complete)  //報錯“指定的轉換無效”                //    Application.DoEvents();                browser.Document.Write(htmlcode);                //MessageBox.Show(browser.DocumentText);                HtmlDocument document = browser.Document;                HtmlElementCollection elems = browser.Document.GetElementsByTagName("a");                foreach (HtmlElement em in elems)                {                    if (em.InnerText == "點擊")                    {                                  em.InvokeMember("click");//alert("觸發點擊事件")                    }                }            }            catch (Exception ex)            {                MessageBox.Show(ex.Message);            }            finally            {                //MessageBox.Show("當前執行線程:"+Thread.CurrentThread.Name);            }        }        //WebClient取網頁源碼        private string GetHtmlSource(string Url)        {            string text1 = "";            try            {                WebClient wc = new WebClient();                text1 = wc.DownloadString(Url);            }            catch (Exception ex)            {                MessageBox.Show(ex.Message);            }            return text1;        }    }}

test.html:

<html><head><title></title><script type="text/javascript" src="a.js"></script></head><body><a href="javascript:void();" onclick="t()">點擊</a></body></html>

js:

<script type="text/javascript">function t(){    alert('ddd');}</script>

原創文章,轉載請註明出處:http://www.cnblogs.com/hongfei/archive/2013/01/05/2846933.html

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.