简体   繁体   中英

how to wait c# webbrowser to complete document load in TPL

Hi I have this two blocks of code

when I navigate the browser to a url and try to wait for it I get a deadlock I think=) any help suggestions are much appreciated!

I'm just adding some more text here so I am able to post the question :/ sorry

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();
                }));

            });

        }

and

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");

            }


        }

You can use TaskCompletionSource to create a task and await for it after the page is loaded.

See: UWP WebView await navigate .

You need to create only one separate thread for WinForms. Other threads will be created by individual browsers themselves. What you do need is handling their DocumentCompleted event. The first time the document completes you enter and submit data, the second time it completes you get the result. When all browsers finish, you exit the winforms thread and you're done.

Note: To launch bots from winforms thread, I made use of Idle event handler, just because it was the first solution that came to my mind. You may find better way.

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;
        }
    }
}

I have experienced this problem before and the solution I have applied is as follows;

 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;
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM