我正在开发 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/
类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
如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我正在使用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].有没有一种方法可以
我在我的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服务器更新战俘
我尝试使用不同的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
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
假设我有一个FireNinja我的数据库中的对象,使用单表继承存储。后来才知道他真的是WaterNinja.将他更改为不同的子类的最干净的方法是什么?更好的是,我很想创建一个新的WaterNinja对象并替换旧的FireNinja在数据库中,保留ID。编辑我知道如何创建新的WaterNinja来self现有FireNinja的对象,我也知道我可以删除旧的并保存新的。我想做的是改变现有项目的类别。我是通过创建一个新对象并执行一些ActiveRecord魔法来替换行,还是通过对对象本身做一些疯狂的事情,或者甚至通过删除它并使用相同的ID重新插入来做到这一点,这是问题的一部分。
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha