Invalid operation from PreviewForm enumerating over modified All lists
trigger-segfault opened this issue · comments
Describe the issue:
The PreviewForm
's refresh action includes updating the animations, models, and textures list. It does so by enumerating through the AllAnimations
, AllEntities
and AllTextures
lists that are stored in Program
. The problem is that these lists can be modified by the parallel scan threads while PreviewForm
is enumerating through them, causing an InvalidOperationException
because the list was modified, thus invalidating the enumeration process.
It looks like the code causing this is Parallel.ForEach
used for ProcessFile
. There's no other situation that could cause this issue, since ReloadItems
is only called by the scan thread after an item is added. But if multiple scan threads are running then this can absolutely happen.
Callstack:
UI Thread:
PreviewForm.UpdateRootEntities(List)
DoScan.AnonymousMethod(PreviewForm)
(refreshAction)PreviewForm.ReloadItems()
Scan Thread:
PreviewForm.ReloadItems()
Program.ScanFiles.AnonymousMethod(RootEntity, long)
Classes.CrocModelReader.LookForCrocModel(BinaryReader, string)
Program.ScanFiles.AnonymousMethod(BinaryReader, string)
Program.ProcessFile(Stream, string, Action)
Program.ProcessFiles.AnonymousMethod(Action)
Solution:
Locking can be used on the list object when adding to each individual list, and when updating/refreshing each individual list. That way only one thread will have access to the list until it's done using it.
Ideally, Add*
functions should added to Program
to automatically handle the locking.