InvokeMember ("click") не работает в элементе управления webBrowser внутри потока - PullRequest
1 голос
/ 23 декабря 2010

Я пытаюсь создать многопоточное приложение, которое создает веб-браузеры и выполняет конкретные действия для каждого из них. Когда я попробовал свой код из основного потока, он работал отлично, однако, когда я изменил код для запуска из потока, код работает нормально, пока не будет вызван 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 () работает очень корректно, когда вызывается из основного потока. Проблема заключается в вызове из другого потока.

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 23 декабря 2010

Вы нарушаете жесткое требование для потока STA, оно должно прокачать цикл сообщений. Вы исправили выход с помощью метода Navigate, вызвав Application.DoEvents (). Это качает цикл сообщений. Но вы не делаете это для InvokeClick.

Проверьте этот ответ для решения. Поместите код в событие DocumentCompleted. Я не вижу очевидного способа решить, когда остановить поток, возможно, вам придется опрашивать какой-то побочный эффект щелчка, возможно, с помощью таймера.

0 голосов
/ 23 декабря 2010

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");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...