Дурачившись с некоторым F # (через MonoDevelop), я написал процедуру, которая перечисляет файлы в каталоге с одним потоком:
let rec loop (path:string) =
Array.append
(
path |> Directory.GetFiles
)
(
path
|> Directory.GetDirectories
|> Array.map loop
|> Array.concat
)
А затем его асинхронная версия:
let rec loopPar (path:string) =
Array.append
(
path |> Directory.GetFiles
)
(
let paths = path |> Directory.GetDirectories
if paths <> [||] then
[| for p in paths -> async { return (loopPar p) } |]
|> Async.Parallel
|> Async.RunSynchronously
|> Array.concat
else
[||]
)
В небольших каталогах асинхронная версия работает нормально. В больших каталогах (например, во многих тысячах каталогов и файлов) асинхронная версия, похоже, зависает. Что мне не хватает?
Я знаю, что создание тысяч потоков никогда не будет самым эффективным решением - у меня всего 8 процессоров, но меня сбивает с толку то, что для больших каталогов асинхронная функция просто не отвечает (даже через полчаса). Тем не менее, это не приводит к явным сбоям, что меня сбивает с толку. Есть ли исчерпанный пул потоков?
Как на самом деле работают эти потоки?
Изменить:
Согласно этому документу:
Mono> = 2.8.x имеет новый пул потоков, который намного сложнее заблокировать. Если вы получаете взаимоблокировку пула потоков, скорее всего, ваша программа пытается зайти в тупик.
:D