В лентяйничать вокруг с некоторыми F # (через MonoDevelop), я написал подпрограмму, которая содержит список файлов в директории с одним потоком:помочь мне причину относительно F # резьба
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 процессоров, но я сбив с толку, что для больших каталогов асинхронная функция просто не отвечает (даже после половины час). Однако это не заметно, но это меня озадачивает. Есть ли пул потоков, который исчерпан?
Как работают эти потоки?
Edit:
По this document:
Mono> = 2.8.x имеет новый ThreadPool, который намного сложнее тупиковой. Если у вас есть тупиковая ситуация с пустым потоком, вероятность того, что ваша программа пытается зайти в тупик.
: D
звучит как тупик ..... –
WRT в тупик, это очень вероятно. Рассмотрим случай, когда нужно закончить каталог папки B, вам нужно добавить потоки X в пул потоков. Однако это блокируется до тех пор, пока предыдущие потоки не закончатся; за исключением того, что они блокируются необходимостью создавать больше потоков в пуле потоков ... –
Для управляемых стеков из зависающей программы $ PID, «kill -QUIT $ PID» и проверки вывода консоли программы. Для собственных стеков: «gdb attach $ PID», затем «t a a bt». –