In goofing um mit einigen F # (via MonoDevelop), habe ich eine Routine geschrieben, die mit einem Thread-Dateien in einem Verzeichnis aufgelistet:helfen mir Grund zu F # Fäden
let rec loop (path:string) =
Array.append
(
path |> Directory.GetFiles
)
(
path
|> Directory.GetDirectories
|> Array.map loop
|> Array.concat
)
Und dann eine asynchrone Version davon:
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
[||]
)
Auf kleinen Verzeichnissen funktioniert die asynchrone Version einwandfrei. Bei größeren Verzeichnissen (z. B. vielen Tausenden von Verzeichnissen und Dateien) scheint die asynchrone Version zu hängen. Was vermisse ich?
Ich weiß, dass das Erstellen von Tausenden von Threads wird nie die effizienteste Lösung sein - ich habe nur 8 CPUs - aber ich bin verblüfft, dass für größere Verzeichnisse die asynchrone Funktion nicht reagiert (auch nach einer Hälfte Stunde). Es versagt jedoch nicht sichtbar, was mich verblüfft. Gibt es einen Threadpool, der erschöpft ist?
Wie funktionieren diese Threads tatsächlich?
Edit:
Nach this document:
Mono> = 2.8.x hat einen neuen Threadpool, die viel, viel schwerer Deadlock. Wenn Sie einen Threadpool-Deadlock erhalten, besteht die Möglichkeit, dass Ihr Programm versucht, sich zu blockieren.
: D
klingt wie Deadlock ..... –
WRT zu einem Deadlock, das ist sehr wahrscheinlich. Betrachten Sie den Fall, in dem das Verzeichnis von Ordner B beendet werden soll, müssen Sie X-Threads zum Thread-Pool hinzufügen. Dies ist jedoch blockiert, bis die vorherigen Threads beendet sind. außer dass sie blockiert werden, indem sie mehr Threads im Thread-Pool erzeugen müssen ... –
Für verwaltete Stacktraces eines gehangenen Programms $ PID, "kill -QUIT $ PID" und überprüfe die Konsolenausgabe des Programms. Für native Stacktraces, "gdb attach $ PID" und dann "t a a bt". –