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