如何等待C#Webbrowser完成TPL中的文档加载

时间:2019-04-08 18:52:10

标签: c# winforms task-parallel-library

嗨,我有这两个代码块

当我将浏览器导航到一个URL并尝试等待它时,我陷入僵局,我认为=)任何帮助建议都将不胜感激!

我只是在此处添加一些文本,因此我可以发布问题:/对不起

foreach (var davaType in davaTypes)
        {
            Parallel.ForEach(years, year =>
            {
                ts.Add(Task.Run(() =>
                {
                    var th = new Thread(async () =>
                    {
                        await doWorkAsync(year, davaType, tarafType);

                        Application.Run();

                    });
                    th.IsBackground = true;
                    th.SetApartmentState(ApartmentState.STA);
                    th.Start();
                }));

            });

        }

public static async Task doWorkAsync(int year, string davaType, string tarafType)
        {
            using (var browser = new MyBrowser())
            {
                Console.WriteLine("Im Created Here");
                 browser.Navigate("some url");

                while (!browser.MyLoaded)
                {
                    Console.WriteLine("waiting");
                    await Task.Delay(10);
                }

                Console.WriteLine("complete");
                browser.Document?.GetElementById("DropDownList1")?.SetAttribute("value", davaType);
                browser.Document.GetElementById("DropDownList3")?.SetAttribute("value", tarafType);
                browser.Document.GetElementById("DropDownList4")?.SetAttribute("value", year.ToString());
                browser.Document.GetElementById("Button1").MyClick();
                await browser.WaitPageLoad(10);
                Console.WriteLine("Im DoneHere");

            }


        }

3 个答案:

答案 0 :(得分:0)

您可以使用TaskCompletionSource创建一个任务,并在页面加载后等待它。

请参阅:UWP WebView await navigate

答案 1 :(得分:0)

您只需要为WinForms创建一个单独的线程。其他线程将由各个浏览器自己创建。您需要做的是处理其DocumentCompleted事件。文档第一次完成时,您输入并提交数据,第二次完成时,您得到结果。当所有浏览器完成后,您退出winforms线程并完成操作。

注意:为了从winforms线程启动机器人,我使用了Idle事件处理程序,只是因为这是我想到的第一个解决方案。您可能会找到更好的方法。

using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;

namespace ConsoleBrowsers
{
    class Program
    {
        static void Main(string[] args)
        {
            string url = "https://your.url.com";
            string[] years = { "2001", "2002", "2003"};
            string[] davas = { "1", "2", "3" };
            string taraf = "1";

            int completed = 0, succeeded = 0;
            var bots = new List<Bot>();
            var started = false;

            var startBots = (EventHandler)delegate (object sender, EventArgs b)
            {
                if (started)
                    return;

                started = true;
                foreach (var dava in davas)
                    foreach (var year in years)
                        bots.Add(new Bot { Year = year, Dava = dava, Taraf = taraf, Url = url }.Run((bot, result) =>
                        {
                            Console.WriteLine($"{result}: {bot.Year}, {bot.Dava}");
                            succeeded += result ? 1 : 0;
                            if (++completed == years.Length * davas.Length)
                                Application.ExitThread();
                        }));
            };

            var forms = new Thread((ThreadStart) delegate {
                Application.EnableVisualStyles();
                Application.Idle += startBots;
                Application.Run();
            });

            forms.SetApartmentState(ApartmentState.STA);
            forms.Start();
            forms.Join();

            Console.WriteLine($"All bots finished, succeeded: {succeeded}, failed:{bots.Count - succeeded}.");
        }
    }

    class Bot
    {
        public string Url, Dava, Taraf, Year;
        public delegate void CompletionCallback(Bot sender, bool result);

        WebBrowser browser;
        CompletionCallback callback;
        bool submitted;

        public Bot Run(CompletionCallback callback)
        {
            this.callback = callback;

            browser = new WebBrowser();
            browser.ScriptErrorsSuppressed = true;
            browser.DocumentCompleted += Browser_DocumentCompleted;
            browser.Navigate(Url);
            return this;
        }

        void Browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            if (browser.ReadyState == WebBrowserReadyState.Complete)
            {
                if (submitted)
                {
                    callback(this, true);
                    return;
                }

                var ok = SetValue("DropDownList1", Dava);
                ok &= SetValue("DropDownList3", Taraf);
                ok &= SetValue("DropDownList4", Year);
                if (ok)
                    ok &= Click("Button1");

                if (!(submitted = ok))
                    callback(this, false);
            }
        }

        bool SetValue(string id, string value, string name = "value")
        {
            var e = browser?.Document?.GetElementById(id);
            e?.SetAttribute(name, value);
            return e != null;
        }

        bool Click(string id)
        {
            var element = browser?.Document?.GetElementById(id);
            element?.InvokeMember("click");
            return element != null;
        }
    }
}

答案 2 :(得分:0)

我以前曾遇到过此问题,我所采用的解决方案如下;

 private void waitTillLoad()
    {
        WebBrowserReadyState loadStatus = default(WebBrowserReadyState);
        int waittime = 100000;
        int counter = 0;
        while (true)
        {
            loadStatus = webBrowser1.ReadyState;
            Application.DoEvents();

            if ((counter > waittime) || (loadStatus == WebBrowserReadyState.Uninitialized) || (loadStatus == WebBrowserReadyState.Loading) || (loadStatus == WebBrowserReadyState.Interactive))
            {
                break; // TODO: might not be correct. Was : Exit While
            }
            counter += 1;
        }
        counter = 0;
        while (true)
        {
            loadStatus = webBrowser1.ReadyState;
            Application.DoEvents();

            if (loadStatus == WebBrowserReadyState.Complete)
            {
                break; // TODO: might not be correct. Was : Exit While
            }

            counter += 1;
        }
    }