我正在尝试创建一个创建WebBrowsers的多线程应用程序,并为每个应用程序执行特定的操作。当我从主线程尝试我的代码时,它工作得很好,但是,当我将代码更改为从线程运行时,代码运行正常,直到调用InvokeMember("click")
并且没有任何反应。 InvokeMember()
未执行,并且未执行按钮单击。这是我的代码:
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(Work);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
[STAThread]
void Work()
{
WebBrowser wb = new WebBrowser();
wb.ScriptErrorsSuppressed = false;
wb.Visible = true;
wb.Navigate("http://website.com");
while (wb.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
//updateText("Loaded");
wb.Document.GetElementById("F1").SetAttribute("Value", "Test");
wb.Document.GetElementById("F2").SetAttribute("Value", "Saracostaz");
wb.Document.GetElementById("F3").SetAttribute("Value", "Tester5123@hotmail.com");
wb.Document.GetElementById("F4").SetAttribute("Value", "Tester5123@hotmail.com");
wb.Document.GetElementById("F5").SetAttribute("Value", "limewire");
wb.Document.GetElementById("F6").SetAttribute("SelectedIndex", "1");
wb.Document.GetElementById("F7").SetAttribute("SelectedIndex", "2");
wb.Document.GetElementById("F8").SetAttribute("SelectedIndex", "5");
wb.Document.GetElementById("F9").SetAttribute("SelectedIndex", "20");
// updateText("Entered Data");
HtmlElementCollection elements = wb.Document.Body.All;
foreach (HtmlElement element in elements)
{
string valueAttribute = element.GetAttribute("value");
if (!string.IsNullOrEmpty(valueAttribute) && valueAttribute == "Sign Up")
{
element.InvokeMember("click");
//MessageBox.show("I am in"); //that messagebox shows normally.
break;
}
}
}
请注意,从主线程调用Work()时,它运行得非常正确。问题在于从另一个线程调用它。
提前致谢。
答案 0 :(得分:1)
您违反了对STA线程的硬性要求,它必须抽取消息循环。通过调用Application.DoEvents(),您可以使用Navigate方法解决问题。这会消息循环。但是你没有为InvokeClick做这件事。
检查this answer以获取解决方案。将代码放在DocumentCompleted事件中。我没有明显的方法来决定何时停止该线程,你可能需要使用计时器轮询点击的某种副作用。
答案 1 :(得分:0)
JFYI,你可以使用LINQ做下一步:
var element = elements
.OfType<HtmlElement>()
.Select(element => element.GetAttribute("value"))
.FirstOrDefault(value=> String.Equals(value, "Sign Up"));
if (element != null)
element.InvokeMember("click");