Проблема с вашим подходом состоит в том, что RunSynchronously
блокирует поток, который вы пытаетесь использовать для запуска остальной части асинхронного вычисления, используя Async.SwitchToContext ctx
.
При использовании F # Interactive, есть одна главнаяПоток, который работает в F # Interactive и обрабатывает взаимодействия с пользователем.Это поток, который может использовать элементы управления Windows Forms, поэтому вы правильно создаете WebBrowser
за пределами async
.Ожидание DocumentCompleted
происходит в потоке пула потоков (который выполняет асинхронный рабочий процесс), но при попытке вернуться к основному потоку он уже блокируется Async.RunSynchronously
.
. Вы можете избежатьблокирование потока путем запуска цикла, который вызывает Application.DoEvents
для обработки событий в основном потоке (что также позволит ему выполнять остальную часть асинхронного выполнения).Ваш downloadWebSite
остается прежним, но теперь вы ждете, используя:
let test =
downloadWebSite (Uri "http://www.google.com") Some
|> Async.Ignore
|> Async.StartAsTask
while not test.IsCompleted do
System.Threading.Thread.Sleep(100)
System.Windows.Forms.Application.DoEvents()
Это немного хак - и, возможно, есть лучший способ структурировать это, если вам действительно не нужно ждатьрезультат (например, просто вернуть задачу и подождать перед выполнением следующей команды), но это должно сработать.