C# プログラムでの WebBrowsing の自動化に問題があります。以前に BHO にコードを使用したことがあり、そこでは機能していました。しかし、純粋な c# プログラム内では、ある種のデッドロックがあるようです。検索ボタンをクリックしてから、documentcomplete が通知されるまで (manualresetevent を介して) 待機するようにプログラムに指示しました。しかし、ManualResetEvent がタイムアウトを通知するまで、検索ボタンのクリックは処理されないようです。その後、クリックが行われ、DocumentComplete-Event も発生します。
そのプログラムの構造について: WebBrowser-Control は WindowsForm の一部です。WebBrowser コントロールは、スレッドを実行するクラスに渡されます。このクラスは、ロードされた Web ブラウザーに応じた具体的な動作がプログラムされている別のクラスに制御を再び渡しました。
したがって、コードでは次のようになります。
スレッドのセットアップ
_runner = new Thread(runner); _runner.SetApartmentState(ApartmentState.STA); _runner.IsBackground = true; _runner.Start();
withingtheRunner-Methodの処理
b.placeTipp(workStructure);
PlaceTipp メソッド
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)); } } }
デッドロックが発生している SearchTipp-Method:
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(); } }
ここで何が起こっているのか、誰かアイデアがありますか?
ありがとう
ライトブリンガー