Как ждать завершения асинхронного - PullRequest
5 голосов
/ 05 ноября 2010

Я хотел бы запустить некоторый асинхронный рабочий процесс, затем дождаться его завершения, прежде чем выводить некоторые результаты, например:

let dowork n =
    async {
        do printfn "work %d" n
    }

let creatework() =
    async {
        for x in [1..5] do
            Async.Start(dowork x)
    }

Async.RunSynchronously(creatework())    
printfn "finished"

когда я запускаю это, я хочу, чтобы все вызовы dowork завершились до того, как печать будет завершена. Однако я получаю такие результаты:

работа 2 работа 3 работа 4 работа 5 законченный работа 1

Я попытался удалить асинхронный вызов из creatework (), но «готово» печатается до запуска асинхронных рабочих процессов.

В реальном режиме программа выполняет некоторые операции ввода-вывода, поэтому я хочу дождаться завершения самого медленного, прежде чем продолжить.

Ответы [ 2 ]

9 голосов
/ 05 ноября 2010

Хороший ответ на мой собственный вопрос кажется отстойным, но, похоже, это работает. Кто-то придумает что-нибудь получше, чтобы я мог наградить их ответом:)

let dowork n =
    async {
        do printfn "work %d" n
    }

let creatework() =
    [1..5] |> Seq.map dowork |> Async.Parallel |> Async.RunSynchronously

creatework()    
printfn "finished"

Это дает различный вывод, но "готово" до сих пор всегда последний ...

1 голос
/ 30 ноября 2010

Я обнаружил, что удобно использовать MailboxProcessor, чтобы убедиться, что все побочные эффекты (например, printfn) происходят в одном потоке. Используйте MailboxProcessor.PostAndReply (singleResult) для объединения результатов работы (будь то просто строки для печати) в один и тот же контекст синхронизации и обеспечения другого типа сообщения, который возвращает статистические значения. Можно использовать объединение для типов этих сообщений.

...