【问题标题】:how to wait c# webbrowser to complete document load in TPL如何等待 c# webbrowser 在 TPL 中完成文档加载
【发布时间】:2019-04-17 20:35:00
【问题描述】:

嗨,我有这两个代码块

当我将浏览器导航到一个 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");

            }


        }

【问题讨论】:

  • 摆脱那些线程和 Task.Run 调用一个启动器。你一次混合了太多东西。 ts 到底是什么?哦,为什么是Parallel.For?在我看来,您似乎想同时混合多种不同风格的异步/并发/并行。
  • 我想做的是一次运行多个浏览器,将它们导航到 url 并进行报废
  • @Licentia 我不会按照您的建议那样做。不要使用 Web 浏览器控件,而是将网站数据下载为字符串,例如使用 var result = new System.Net.WebClient().DownloadString(url);。作为奖励,DownloadString() 具有 async 风格,这将使您在清理代码后更轻松地使用 tasks,正如 Peter 所建议的那样。
  • 我知道这是我的第一个意图,但是网站中的发布请求被后端生成的密钥阻止,所以发布请求返回我的 url html :(

标签: c# winforms task-parallel-library


【解决方案1】:

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

请参阅:UWP WebView await navigate

【讨论】:

    【解决方案2】:

    我之前遇到过这个问题,我应用的解决方案如下;

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

    【讨论】:

      【解决方案3】:

      您只需为 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;
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2014-01-08
        • 2018-11-07
        • 1970-01-01
        • 2013-10-31
        • 1970-01-01
        • 2011-10-11
        • 1970-01-01
        • 2011-11-09
        • 1970-01-01
        相关资源
        最近更新 更多