• 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控件的窗口,

    实现多线程加速,

    如果一个网页崩溃,不会导致整个程序关闭。

    源码下载:https://files.cnblogs.com/kofip/WebBrowserTest.rar

    简化后源码:https://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

  • 相关阅读:
    DOM解析和SAX解析对比
    SAX解析示例代码和原理
    xPath技术
    dom4j工具对XML写入修改删除操作实现
    Dom4j工具j解析XML原理和示例代码
    Servlet的多线程并发问题
    Servlet的自动加载
    servlet缺省路径
    线程安全问题出现 的根本原因和解决方案
    9.12測试(四)——測试笔
  • 原文地址:https://www.cnblogs.com/Ruiky/p/2701623.html
Copyright © 2020-2023  润新知