我有一个关于在C#程序中自动化WebBrowsing的问题。
我之前在一个BHO中使用过这段代码,而在纯C#程序中似乎存在一种死锁。我已经指示程序点击搜索按钮,然后等待(通过ManualResetEvent)documentcomplete信号。但现在似乎点击搜索按钮直到ManualResetEvent信号超时才会被处理。此后,点击会被执行,并且DocumentComplete事件也会触发。
关于程序结构: WebBrowser-Control是WindowsForm的一部分。WebBrowser Control被传递给运行线程的类。这个类再次将控件传递给另一个类,在这个类中编写了根据加载的WebBrowser具体行为的程序。
所以在代码中看起来是这样的:
关于程序结构: WebBrowser-Control是WindowsForm的一部分。WebBrowser Control被传递给运行线程的类。这个类再次将控件传递给另一个类,在这个类中编写了根据加载的WebBrowser具体行为的程序。
所以在代码中看起来是这样的:
Setup of the thread
_runner = new Thread(runner); _runner.SetApartmentState(ApartmentState.STA); _runner.IsBackground = true; _runner.Start();
Processing of withingthe Runner-Method
b.placeTipp(workStructure);
The PlaceTipp-Method
public void placeTipp(ref OverallTippStructure tipp) { _expectedUrl = String.Empty; _betUrl = String.Empty; _status = BookieStatusType.CHECKLOGIN; while (true) { _mreWaitForAction.Reset(); checkIETab(); switch (_status) { case BookieStatusType.REQUESTWEBSITE: ConsoleWriter.writeToConsole(String.Format("Bookie {0}: Keine IE-Tab vorhanden. Fordere eine an", this.BookieName)); //if (RequestIETabEvent != null) // RequestIETabEvent(this, new EventArgs()); _status = BookieStatusType.NAVIGATETOWEBSITE; _mreWaitForAction.Set(); break; case BookieStatusType.NAVIGATETOWEBSITE: _webBrowser.Navigate(@"http://www.nordicbet.com"); break; case BookieStatusType.CHECKLOGIN: checkLogin(); break; case BookieStatusType.LOGINNEEDED: doLogin(); break; case BookieStatusType.LOGGEDIN: _status = BookieStatusType.SEARCHTIPP; _mreWaitForAction.Set(); break; case BookieStatusType.SEARCHTIPP: searchTipp(tipp); break; case BookieStatusType.NAVTOSB: NavToSB(); break; case BookieStatusType.GETMARKET: getMarket(tipp); break; case BookieStatusType.PLACEBET: placeBet(tipp); break; case BookieStatusType.CONFIRMBET: confirmBet(); break; case BookieStatusType.EXTRACTBETDATA: extractBetId(ref tipp); break; case BookieStatusType.FINISHED: return; } if (!_mreWaitForAction.WaitOne(60000)) { //Sonderüberpüfung be LoginNeeded if (_status == BookieStatusType.LOGINNEEDED) { //checkLogin(); throw new BookieLoginFailedExcpetion(); } //TIMEOUT! ConsoleWriter.writeToConsole(String.Format("Bookie {0}: Timeout bei warten auf nächsten Schritt. Status war {1}", this.BookieName, this._status.ToString())); throw new BookieTimeoutExcpetion(String.Format("Bookie {0}: Timeout bei dem Warten auf Ereignis", this.BookieName)); } } }
The SearchTipp-Method where the Deadlock is happening:
private void searchTipp(OverallTippStructure tipp) { if (_webBrowser.InvokeRequired) { _webBrowser.Invoke(new delegatePlaceBet(searchTipp), new object[] { tipp }); } else { ConsoleWriter.writeToConsole(String.Format("Bookie {0}: Suche Tipp {1}", this.BookieName, tipp.BookieMatchName)); _expectedUrl = String.Empty; if (!_webBrowser.Url.ToString().StartsWith("https://www.nordicbet.com/eng/sportsbook")) { ConsoleWriter.writeToConsole(String.Format("Bookie {0}: Nicht auf Sportsbookseite. Navigiere", this.BookieName)); _status = BookieStatusType.NAVTOSB; _mreWaitForAction.Set(); return; } _searchCompleted = false; HtmlDocument doc = _webBrowser.Document; if (doc != null) { mshtml.IHTMLInputElement elemSearch = (mshtml.IHTMLInputElement)doc.GetElementById("query").DomElement; if (elemSearch != null) { Thread.Sleep(Delayer.delay(2000, 10000)); elemSearch.value = tipp.BookieMatchName; mshtml.IHTMLElement elemSearchButton = (mshtml.IHTMLElement)doc.GetElementById("search_button").DomElement; if (elemSearchButton != null) { Thread.Sleep(Delayer.delay(900, 4000)); elemSearchButton.click(); //elemSearchButton.InvokeMember("click"); if (!_mreWaitForAction.WaitOne(10000)) //Here The Deadlock happens { //Now the click event and therefor the search will be executed ConsoleWriter.writeToConsole(String.Format("Bookie {0}: Suche ist auf Timeout gelaufen", this.BookieName)); throw new BookieTimeoutExcpetion(String.Format("Bookie {0}: Suche ist auf Timeout gelaufen", this.BookieName)); } _mreWaitForAction.Reset(); HtmlElement spanResult = doc.GetElementById("total_ocs_count"); while (spanResult == null) { Thread.Sleep(500); spanResult = doc.GetElementById("total_ocs_count"); } int total_ocs_count = 0; if (!Int32.TryParse(spanResult.InnerHtml, out total_ocs_count)) { ConsoleWriter.writeToConsole(String.Format("Bookie {0}: Tip {1} nicht gefunden", this.BookieName, tipp.BookieMatchName)); throw new BookieTippNotFoundExcpetion(String.Format("Bookie {0}: Tip {1} nicht gefunden", this.BookieName, tipp.BookieMatchName)); } if (total_ocs_count <= 0) { ConsoleWriter.writeToConsole(String.Format("Bookie {0}: Tip {1} nicht gefunden", this.BookieName, tipp.BookieMatchName)); throw new BookieTippNotFoundExcpetion(String.Format("Bookie {0}: Tip {1} nicht gefunden", this.BookieName, tipp.BookieMatchName)); } /* else if (total_ocs_count > 1) { throw new BookieMoreThanOneFoundExcpetion(String.Format("Bookie {0}: Tipp {1} nicht eindeutig", this.BookieName, tipp.BookieMatchName)); } */ ConsoleWriter.writeToConsole(String.Format("Bookie {0}: Tip {1} gefunden", this.BookieName, tipp.BookieMatchName)); _status = BookieStatusType.GETMARKET; } } } _mreWaitForAction.Set(); } }