Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Here is how to organize a message loop on a non-UI thread, to run asynchronous tasks like <code>WebBrowser</code> automation. It uses <a href="https://stackoverflow.com/tags/async-await/info"><code>async/await</code></a> to provide the convenient linear code flow and loads a set of web pages in a loop. The code is a ready-to-run console app which is partially based on <a href="https://stackoverflow.com/a/18675926/1768303">this excellent post</a>.</p> <p>Related answers:</p> <ul> <li><a href="https://stackoverflow.com/a/22262976/1768303">https://stackoverflow.com/a/22262976/1768303</a> </li> <li><a href="https://stackoverflow.com/a/21775343/1768303">https://stackoverflow.com/a/21775343/1768303</a></li> </ul> <p></p> <pre><code>using System; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace ConsoleApplicationWebBrowser { // by Noseratio - https://stackoverflow.com/users/1768303/noseratio class Program { // Entry Point of the console app static void Main(string[] args) { try { // download each page and dump the content var task = MessageLoopWorker.Run(DoWorkAsync, "http://www.example.com", "http://www.example.net", "http://www.example.org"); task.Wait(); Console.WriteLine("DoWorkAsync completed."); } catch (Exception ex) { Console.WriteLine("DoWorkAsync failed: " + ex.Message); } Console.WriteLine("Press Enter to exit."); Console.ReadLine(); } // navigate WebBrowser to the list of urls in a loop static async Task&lt;object&gt; DoWorkAsync(object[] args) { Console.WriteLine("Start working."); using (var wb = new WebBrowser()) { wb.ScriptErrorsSuppressed = true; TaskCompletionSource&lt;bool&gt; tcs = null; WebBrowserDocumentCompletedEventHandler documentCompletedHandler = (s, e) =&gt; tcs.TrySetResult(true); // navigate to each URL in the list foreach (var url in args) { tcs = new TaskCompletionSource&lt;bool&gt;(); wb.DocumentCompleted += documentCompletedHandler; try { wb.Navigate(url.ToString()); // await for DocumentCompleted await tcs.Task; } finally { wb.DocumentCompleted -= documentCompletedHandler; } // the DOM is ready Console.WriteLine(url.ToString()); Console.WriteLine(wb.Document.Body.OuterHtml); } } Console.WriteLine("End working."); return null; } } // a helper class to start the message loop and execute an asynchronous task public static class MessageLoopWorker { public static async Task&lt;object&gt; Run(Func&lt;object[], Task&lt;object&gt;&gt; worker, params object[] args) { var tcs = new TaskCompletionSource&lt;object&gt;(); var thread = new Thread(() =&gt; { EventHandler idleHandler = null; idleHandler = async (s, e) =&gt; { // handle Application.Idle just once Application.Idle -= idleHandler; // return to the message loop await Task.Yield(); // and continue asynchronously // propogate the result or exception try { var result = await worker(args); tcs.SetResult(result); } catch (Exception ex) { tcs.SetException(ex); } // signal to exit the message loop // Application.Run will exit at this point Application.ExitThread(); }; // handle Application.Idle just once // to make sure we're inside the message loop // and SynchronizationContext has been correctly installed Application.Idle += idleHandler; Application.Run(); }); // set STA model for the new thread thread.SetApartmentState(ApartmentState.STA); // start the thread and await for the task thread.Start(); try { return await tcs.Task; } finally { thread.Join(); } } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload