1. ホーム
  2. c#

[解決済み] 新しいスレッドでWebBrowserコントロール

2023-05-30 06:21:58

質問

私はクリックされたいUriのリストを持っています。これを達成するために、私はUriごとに新しいWebブラウザコントロールを作成しようとしています。私は、Uriごとに新しいスレッドを作成します。私が抱えている問題は、ドキュメントが完全にロードされる前にスレッドが終了することです。どのように私はこれを克服することができますか?

var item = new ParameterizedThreadStart(ClicIt.Click); 
var thread = new Thread(item) {Name = "ClickThread"}; 
thread.Start(uriItem);

public static void Click(object o)
{
    var url = ((UriItem)o);
    Console.WriteLine(@"Clicking: " + url.Link);
    var clicker = new WebBrowser { ScriptErrorsSuppressed = true };
    clicker.DocumentCompleted += BrowseComplete;
    if (String.IsNullOrEmpty(url.Link)) return;
    if (url.Link.Equals("about:blank")) return;
    if (!url.Link.StartsWith("http://") && !url.Link.StartsWith("https://"))
        url.Link = "http://" + url.Link;
    clicker.Navigate(url.Link);
}

どのように解決するのですか?

メッセージループを汲み上げるSTAスレッドを作成する必要があります。 これは、WebBrowserのようなActiveXコンポーネントにとって唯一の快適な環境です。 そうしないと、DocumentCompleted イベントを取得することができません。 いくつかのサンプルコードです。

private void runBrowserThread(Uri url) {
    var th = new Thread(() => {
        var br = new WebBrowser();
        br.DocumentCompleted += browser_DocumentCompleted;
        br.Navigate(url);
        Application.Run();
    });
    th.SetApartmentState(ApartmentState.STA);
    th.Start();
}

void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
    var br = sender as WebBrowser;
    if (br.Url == e.Url) {
        Console.WriteLine("Natigated to {0}", e.Url);
        Application.ExitThread();   // Stops the thread
    }
}