У меня есть список Uri, по которым я хочу "щелкнуть". Для этого я пытаюсь создать новый элемент управления в веб-браузере для каждого Uri. Я создаю новый поток для каждого Uri. Проблема, с которой я сталкиваюсь, - это конец потока перед документом. полностью загружен, поэтому я никогда не смогу воспользоваться событием DocumentComplete. Как мне это преодолеть?
var item = new ParameterizedThreadStart(ClicIt.Click);
var thread = new Thread(item) {Name = "ClickThread"};
thread.Start(uriItem);
public static void Click(object o)
{
var url = ((UriItem)o);
Console.WriteLine(@"Clicking: " + url.Link);
var clicker = new WebBrowser { ScriptErrorsSuppressed = true };
clicker.DocumentCompleted += BrowseComplete;
if (String.IsNullOrEmpty(url.Link)) return;
if (url.Link.Equals("about:blank")) return;
if (!url.Link.StartsWith("http://") && !url.Link.StartsWith("https://"))
url.Link = "http://" + url.Link;
clicker.Navigate(url.Link);
}
c#
multithreading
browser
Искусство W
источник
источник
WebBrowser
объект в живых (для сохранения состояния / файлов cookie и т. Д.) И выполнять несколькоNavigate()
вызовов с течением времени. Но я не уверен, кудаApplication.Run()
направить вызов, потому что он блокирует выполнение дальнейшего кода. Какие-нибудь подсказки?Application.Exit();
чтобы датьApplication.Run()
вернуться.Вот как организовать цикл сообщений в потоке без пользовательского интерфейса для выполнения асинхронных задач, таких как
WebBrowser
автоматизация. Он используетсяasync/await
для обеспечения удобного линейного потока кода и загрузки набора веб-страниц в цикле. Код представляет собой готовое к запуску консольное приложение, частично основанное на этом отличном посте .Связанные ответы:
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<object> DoWorkAsync(object[] args) { Console.WriteLine("Start working."); using (var wb = new WebBrowser()) { wb.ScriptErrorsSuppressed = true; TaskCompletionSource<bool> tcs = null; WebBrowserDocumentCompletedEventHandler documentCompletedHandler = (s, e) => tcs.TrySetResult(true); // navigate to each URL in the list foreach (var url in args) { tcs = new TaskCompletionSource<bool>(); 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<object> Run(Func<object[], Task<object>> worker, params object[] args) { var tcs = new TaskCompletionSource<object>(); var thread = new Thread(() => { EventHandler idleHandler = null; idleHandler = async (s, e) => { // 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(); } } } }
источник
task.Wait();
. Я что то не так делаю?По моему опыту в прошлом, веб-браузер не любит работать вне основного потока приложения.
Попробуйте вместо этого использовать httpwebrequests, вы можете установить их как асинхронные и создать обработчик для ответа, чтобы знать, когда он будет успешным:
как использовать-httpwebrequest-net-асинхронно
источник
webRequest.Credentials = CredentialsCache.DefaultCredentials;
Credentials
свойством объекта и как заполнять HTML.WindowsIdentity.GetCurrent().Name
после реализации олицетворения и, если хотите, протестировать их с помощью поиска AD. Не уверен, как для этого будут использоваться файлы cookie и кеш.WebBrowser
что будет указывать на то, что страницы HTML загружаются, OP даже сказал, чтоWebRequest
не достигнет того, чего он хочет, поэтому, если веб-сайт ожидает ввода HTML для входа в систему, установкаCredentials
объекта не будет работать. Кроме того, как сообщает OP, на сайтах есть Facebook; В этом случае проверка подлинности Windows не работает.Простое решение, при котором происходит одновременная работа нескольких веб-браузеров
Напишите следующий обработчик кликов button1:
textBox1.Clear(); textBox1.AppendText(DateTime.Now.ToString() + Environment.NewLine); int completed_count = 0; int count = 10; for (int i = 0; i < count; i++) { int tmp = i; this.BeginInvoke(new Action(() => { var wb = new WebBrowser(); wb.ScriptErrorsSuppressed = true; wb.DocumentCompleted += (cur_sender, cur_e) => { var cur_wb = cur_sender as WebBrowser; if (cur_wb.Url == cur_e.Url) { textBox1.AppendText("Task " + tmp + ", navigated to " + cur_e.Url + Environment.NewLine); completed_count++; } }; wb.Navigate("/programming/4269800/webbrowser-control-in-a-new-thread"); } )); } while (completed_count != count) { Application.DoEvents(); Thread.Sleep(10); } textBox1.AppendText("All completed" + Environment.NewLine);
источник