Dưới đây là cách tổ chức vòng lặp thông báo trên một chuỗi không phải giao diện người dùng, để chạy các tác vụ không đồng bộ như WebBrowser
tự động hóa. Nó sử dụng async/await
để cung cấp luồng mã tuyến tính thuận tiện và tải một tập hợp các trang web trong một vòng lặp. Mã là một ứng dụng bảng điều khiển sẵn sàng chạy, một phần dựa trên bài đăng tuyệt vời này .
Các câu trả lời liên quan:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ConsoleApplicationWebBrowser
{
class Program
{
static void Main(string[] args)
{
try
{
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();
}
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);
foreach (var url in args)
{
tcs = new TaskCompletionSource<bool>();
wb.DocumentCompleted += documentCompletedHandler;
try
{
wb.Navigate(url.ToString());
await tcs.Task;
}
finally
{
wb.DocumentCompleted -= documentCompletedHandler;
}
Console.WriteLine(url.ToString());
Console.WriteLine(wb.Document.Body.OuterHtml);
}
}
Console.WriteLine("End working.");
return null;
}
}
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) =>
{
Application.Idle -= idleHandler;
await Task.Yield();
try
{
var result = await worker(args);
tcs.SetResult(result);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
Application.ExitThread();
};
Application.Idle += idleHandler;
Application.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
try
{
return await tcs.Task;
}
finally
{
thread.Join();
}
}
}
}