WebBrowser 多線程問題,尋求解答!(已經搞清楚!) 【轉】


 1 using System;  2 using System.Threading;  3 using System.Windows.Forms;  4 
 5 namespace WebBrowserTest  6 {  7     public partial class MainForm : Form  8  {  9         public MainForm() 10  { 11  InitializeComponent(); 12  } 13 
14         public static ChildForm childForm; 15 
16         private void MainForm_Load(object sender, EventArgs e) 17  { 18             this.Text = string.Format("線程ID:{0}", Thread.CurrentThread.ManagedThreadId); 19  } 20 
21         private void button1_Click(object sender, EventArgs e) 22  { 23             Thread thread = new Thread(new ThreadStart(this.CreateForm)); 24  thread.SetApartmentState(ApartmentState.STA); 25             thread.IsBackground = true; 26  thread.Start(); 27  } 28 
29         private void CreateForm() 30  { 31             MainForm.childForm = new ChildForm(); 32             MainForm.childForm.webBrowser.Navigate("http://tieba.baidu.com/"); //這里不是UI線程,為什么也能導航呢?
33  MainForm.childForm.ShowDialog(); 34  } 35 
36         private void button2_Click(object sender, EventArgs e) 37  { 38             if (MainForm.childForm != null && MainForm.childForm.IsHandleCreated) 39  { 40                 //如果不調用childForm窗口的Invoke方法修改標題,就報異常! 41                 //線程間操作無效: 從不是創建控件“ChildForm”的線程訪問它。
42 
43                 MainForm.childForm.Invoke(new MethodInvoker(delegate
44  { 45                     MainForm.childForm.Text = string.Format("線程ID:{0}", Thread.CurrentThread.ManagedThreadId); 46  })); 47 
48 
49 
50                 //為什么這里就能正常導航頁面呢? 51                 //難道WebBrowser控件,始終都在UI線程運行? 52                 //即使創建它的線程,不是UI線程?
53 
54                 MainForm.childForm.webBrowser.Navigate("http://www.baidu.com/"); 55  } 56  } 57  } 58 }

 

 

 

 

 

但是神奇的地方就是,操作WebBrowser進行網頁導航,就可以不調用 Invoke 方法,不報異常。這是為什么呢?

這個環境下 WebBrowser 是運行在那個線程呢? 主線程? 還是新的子線程?

 

簡化代碼后,結果一樣。

 

復制代碼
using System; using System.Threading; using System.Windows.Forms; namespace WebBrowserTest { public partial class MainForm : Form { public MainForm() { InitializeComponent(); } private Form childForm; private WebBrowser webBrowser; private void MainForm_Load(object sender, EventArgs e) { this.Text = string.Format("線程ID:{0}", Thread.CurrentThread.ManagedThreadId); } private void button1_Click(object sender, EventArgs e) { Thread thread = new Thread(new ThreadStart(this.CreateForm)); thread.SetApartmentState(ApartmentState.STA); thread.IsBackground = true; thread.Start(); } private void CreateForm() { this.childForm = new Form(); this.webBrowser = new WebBrowser(); this.webBrowser.Dock = DockStyle.Fill; this.childForm.Controls.Add(this.webBrowser); this.webBrowser.Navigate("http://tieba.baidu.com/"); //這里不是UI線程,為什么也能導航呢?

            this.childForm.ShowDialog(); } private void button2_Click(object sender, EventArgs e) { if (this.childForm != null && this.childForm.IsHandleCreated) { //如果不調用childForm窗口的Invoke方法修改標題,就報異常! //線程間操作無效: 從不是創建控件“ChildForm”的線程訪問它。

                this.childForm.Invoke(new MethodInvoker(delegate { this.childForm.Text = string.Format("線程ID:{0}", Thread.CurrentThread.ManagedThreadId); //這樣修改是正常的。
 })); this.childForm.Text = "修改標題"; //這樣修改就報異常了! //為什么這里就能正常導航頁面呢? //難道WebBrowser控件,始終都在UI線程運行? //即使創建它的線程,不是UI線程?

                this.webBrowser.Navigate("http://www.baidu.com/"); } } } }
復制代碼

 

 

此問題尋求解答,

目的:

現在多標簽瀏覽器 它每個標簽都是一個線程在執行

其中一個標簽頁面 崩潰 不影響到其他 標簽頁面

 

新線程創建帶有WebBrowser控件的窗口,

實現多線程加速,

如果一個網頁崩潰,不會導致整個程序關閉。

源碼下載:http://files.cnblogs.com/kofip/WebBrowserTest.rar

簡化后源碼:http://files.cnblogs.com/kofip/WebBrowserTest2.rar

 

終於弄清楚了,.Net 1.0時代 非UI線程可以直接 操作UI控件

到了.NET 2.0開始 就不能直接操作UI控件了,

但是WebBrowser屬於系統COM組件,.Net團隊沒有添加,檢查操作線程機制。

但是實質上,也應該存在此類問題,只是他內部沒有做檢測罷了。

 

 

復制代碼
using System; using System.Threading; using System.Windows.Forms; namespace WebBrowserTest { public partial class MainForm : Form { public MainForm() { InitializeComponent(); } private Form childForm; private WebBrowser webBrowser; private void MainForm_Load(object sender, EventArgs e) { this.Text = string.Format("線程ID:{0}", Thread.CurrentThread.ManagedThreadId); } private void button1_Click(object sender, EventArgs e) { Thread thread = new Thread(new ThreadStart(this.CreateForm)); thread.SetApartmentState(ApartmentState.STA); thread.IsBackground = true; thread.Start(); } private void CreateForm() { this.childForm = new Form(); this.webBrowser = new WebBrowser(); this.webBrowser.Dock = DockStyle.Fill; this.webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(this.webBrowser_DocumentCompleted); this.childForm.Controls.Add(this.webBrowser); //this.webBrowser.Navigate("http://tieba.baidu.com/"); //這里不是UI線程,為什么也能導航呢?

            this.childForm.ShowDialog(); } private void button2_Click(object sender, EventArgs e) { if (this.childForm != null && this.childForm.IsHandleCreated) { //如果不調用childForm窗口的Invoke方法修改標題,就報異常! //線程間操作無效: 從不是創建控件“ChildForm”的線程訪問它。

                int threadId = Thread.CurrentThread.ManagedThreadId; this.childForm.Invoke(new MethodInvoker(delegate { this.childForm.Text = string.Format("主線程ID:{0} 子線程ID:{1}", threadId, Thread.CurrentThread.ManagedThreadId); //這樣修改是正常的。
 })); //this.childForm.Text = "修改標題"; //這樣修改就報異常了! //為什么這里就能正常導航頁面呢? //難道WebBrowser控件,始終都在UI線程運行? //即使創建它的線程,不是UI線程?

                this.webBrowser.Navigate("http://www.baidu.com/"); } } private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { if (this.webBrowser.ReadyState == WebBrowserReadyState.Complete) { MessageBox.Show(string.Format("WebBrowser線程ID:{0}", Thread.CurrentThread.ManagedThreadId)); } } } }
復制代碼

 

 轉自:http://www.cnblogs.com/kofip/archive/2012/09/24/2699477.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM