jjzjj

c# - 从线程访问和更改 winform webbrowser

coder 2024-06-19 原文

我正在开发 Windows 应用程序,其中有一个 tabControl,用户可以在其中打开多个选项卡,就像 IE 一样。现在我必须访问选定的选项卡,然后必须对打开的文档执行一些操作。

我能够访问它,但是在访问选定的选项卡并执行操作之后

当我使用另一个线程执行此任务时,应用程序挂起。

请建议我该怎么做。

我正在使用 .net 4.0。 C#

看下面的代码,这段代码在点击按钮上

   TextToSpeechThread = new Thread(new ThreadStart(ReadWebDocument));
        TextToSpeechThread.Name = ApplicationManager.GlobalThreadNaming.TextToSpeech.ToString();
        TextToSpeechThread.SetApartmentState(ApartmentState.STA);
        TextToSpeechThread.Start();

这是调用操作的线程方法

 browserTabControl.Invoke(new MethodInvoker(delegate
        {

            browserTabControl.SelectedTab.Controls[0].Invoke(new MethodInvoker(delegate
            {
                WebBrowser _browser = (WebBrowser)(browserTabControl.SelectedTab.Controls[0]);

                my_Voice.Speak(_browser.DocumentTitle.ToString(), my_Spflag);

                foreach (var link in _browser.Document.All)
                {
                    HtmlElement elem = (HtmlElement)(link);
                    Thread tempThread = new Thread(new ParameterizedThreadStart(HighlightingWebDocument));
                    tempThread.Start(elem);

                    if (elem.TagName == "A")
                    {
                        if (elem.InnerText != null)
                        {
                            if (elem.InnerText.ToString() != "")
                            {
                                my_Voice.Speak(elem.InnerText.ToString(), my_Spflag);
                            }
                        }
                    }
                    if (elem.TagName == "DIV")
                    {
                        if (elem.InnerText != null)
                        {
                            if (elem.InnerText.ToString() != "")
                            {
                                my_Voice.Speak(elem.InnerText.ToString(), my_Spflag);
                            }
                        }
                        //my_Voice.Speak(elem.TagName.ToString(), my_Spflag);
                    }
                    if (elem.TagName == "IFRAME")
                    {
                        if (elem.InnerText != null)
                        {
                            if (elem.InnerText.ToString() != "")
                            {
                                my_Voice.Speak(elem.InnerText.ToString(), my_Spflag);
                            }
                        }
                    }
                    if (elem.TagName == "SPAN")
                    {
                        if (elem.InnerText != null)
                        {
                            if (elem.InnerText.ToString() != "")
                            {
                                my_Voice.Speak(elem.InnerText.ToString(), my_Spflag);
                            }
                        }
                    }
                    if (elem.TagName == "LINK")
                    {
                        if (elem.InnerText != null)
                        {
                            if (elem.InnerText.ToString() != "")
                            {
                                my_Voice.Speak(elem.InnerText.ToString(), my_Spflag);
                            }
                        }
                    }
                    if (elem.TagName == "INPUT")
                    {
                        if (elem.InnerText != null)
                        {
                            if (elem.InnerText.ToString() != "")
                            {
                                my_Voice.Speak(elem.InnerText.ToString(), my_Spflag);
                            }
                        }

                    }
                    Thread.Sleep(150);
                }
            }));


        }));

现在请提供一些有用的链接...

这是你们建议的另一种方法..

声明委托(delegate)

delegate void HighlightBrowsercontent(HtmlElement elem);
    HighlightBrowsercontent highLightBrowsercontent = null;

在表单加载时

  public Form1()
    {
        InitializeComponent();

        // initialise the delegate to point to an implemntation

        highLightBrowsercontent = new HighlightBrowsercontent(OnHighLightContent);

    }

点击按钮,我想读出内容并突出显示链接。

  private void button1_Click(object sender, EventArgs e)
    {
        HtmlElementCollection links = webBrowser1.Document.Links;

        this.backgroundWorker2.RunWorkerAsync(links);
    }

最后这是我要执行的流程。

 private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
    {
        IAsyncResult res = BeginInvoke(myEnableCancel, new object[] { true });
        ReadDocumetnAsync((HtmlElementCollection)(e.Argument));
        BeginInvoke(myEnableCancel, new object[] { false });
    }

    void ReadDocumetnAsync(HtmlElementCollection elemCollection)
    {
        foreach (var elem in elemCollection)
        {
            HtmlElement elem1 = (HtmlElement)(elem);

            SpeechLib.SpVoice myVoice = new SpeechLib.SpVoice(); ;
            if (elem1.InnerText != null)
            {
                BeginInvoke(highLightBrowsercontent, elem);
                myVoice.Speak(elem1.InnerText);
                System.Threading.Thread.Sleep(450);

                IAsyncResult ar = BeginInvoke(highLightBrowsercontent, elem);// Update the screen
                // Wait until the folder has been created before proceeding with the content of the folde
                while (!ar.IsCompleted)
                {
                    Application.DoEvents();
                    ar.AsyncWaitHandle.WaitOne(-1, false);
                }


            }

        }

    }
 public void OnHighLightContent(HtmlElement element)
    {
        HtmlDocument doc2 = webBrowser1.Document as HtmlDocument;
        toolStripStatusLabel2.Text = element.OuterHtml;
        element.Focus();
        element.ScrollIntoView(false);
        StringBuilder html = new StringBuilder(doc2.Body.OuterHtml);
        String substitution = "<span style='background-color: rgb(255, 255, 0);'>" + element.OuterHtml + "</span>";
        html.Replace(element.OuterHtml, substitution);
        doc2.Body.InnerHtml = html.ToString();
    }

它是只读第一个链接。 我不知道这是怎么回事..

最佳答案

由于 Invoke 调用,此代码在主线程上运行,而不是在您的工作线程上运行。所以是的,它会在开始运行时阻塞 UI,Speak() 需要时间。使用 BeginInvoke 并不能解决这个问题。

首先在 List<string> 中收集字符串,那不应该超过几分之一秒。将该列表传递给工作人员进行发言。

使用 SpeakAsync() 也可以工作,避免线程并使中止说话变得容易得多,但将更难跟踪您在页面上的位置。顺带一提,通过迭代器彻底解决了这个问题,请查看您最喜欢的 C# 语言书籍中的 yield 关键字。

关于c# - 从线程访问和更改 winform webbrowser,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8787697/

有关c# - 从线程访问和更改 winform webbrowser的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  3. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  4. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  5. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  6. ruby - Capistrano 3 在任务中更改 ssh_options - 2

    我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe

  7. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  8. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  9. ruby - 更改 ActiveRecord 中对象的类 - 2

    假设我有一个FireNinja我的数据库中的对象,使用单表继承存储。后来才知道他真的是WaterNinja.将他更改为不同的子类的最干净的方法是什么?更好的是,我很想创建一个新的WaterNinja对象并替换旧的FireNinja在数据库中,保留ID。编辑我知道如何创建新的WaterNinja来self现有FireNinja的对象,我也知道我可以删除旧的并保存新的。我想做的是改变现有项目的类别。我是通过创建一个新对象并执行一些ActiveRecord魔法来替换行,还是通过对对象本身做一些疯狂的事情,或者甚至通过删除它并使用相同的ID重新插入来做到这一点,这是问题的一部分。

  10. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

随机推荐