как ждать c # webbrowser для завершения загрузки документа в TPL - PullRequest
0 голосов
/ 08 апреля 2019

Привет, у меня есть эти два блока кода

, когда я перемещаюсь в браузере по 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 голосов
/ 17 апреля 2019

Вам нужно создать только один отдельный поток для 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;
        }
    }
}
0 голосов
/ 17 апреля 2019

Я уже сталкивался с этой проблемой, и я применил следующее решение:

 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;
        }
    }
0 голосов
/ 09 апреля 2019

Вы можете использовать TaskCompletionSource , чтобы создать задачу и ожидать ее после загрузки страницы.

См .: UWP WebView ждут навигации .

...