Forum > Windows
[SOLVED] How to cleanup ReadDirectoryChangesW operations properly?
ASerge:
Let's go back to the beginning to better understand.
Let the directory tree look like this: Level_0_A\Level_1_A\Level_2_A\. You start monitoring Level_0_A from subtrees (by starting a thread). At some point, you stop monitoring (via stopping the thread).
Then rename Level_2_A to Level_2_B (for example) - there are no errors.
Then rename Level_1_A to Level_1_B - an error occurs.
Do I understand correctly?
d7_2_laz:
Hm, maybe it's easier with a small picture -> attached pic1.
And for simpliness, for the moment forget all monitoring of the tree itself
and think in terms of: monitoring of one single dedicated folder, which's filelist does appear on the right side.
(i need the ReadDirectoryChangesW only for the monitoring of a single folder. That needs much more details information
about changes, ie. file size, date, attribues etc., which would not be needed and overwhelming for a directory tree monitoring at all).
So, clicking onto child node "Level2_A", monitoring will start for folder Level2_A, who's details are needed for the file list informations.
Now: edit caption on the tree node "Level2_A" and rename it to "Level2_A_test".
The thread will be stopped, waiting until terminated, CancelIO and CloseHandle.
Then, after a certain security delay (avoid timing issues), SHFileOperationW is called for to rename the folder.
If successful, the changed folder name will be passed to the file list and the monitoring will restart for the new folder name "Level2_A_test".
Now, click on parent node: Level1_A.
Monitoring is stopped and restarted --> now for the Level1_A folder, and it's details will be displayed in the file list.
Now, When editing Level1_A eg. to "Level1_A_test". SHFileOperationW will fail with "already in use". That was not the case with Delphi 7 (resp win x32?).
The other way round vice versa:
Rename the parent folder Level1_A to Level1_A_test first, and afterwards it's child node (sub folder) Level2_A to Level2_A_test: this does NOT lead to locking issues.
In short: it appears to me that after stopping thread/monitoring for a sub filder, it will be still locked by ReadDirectoryChangesW, forbidding to rename it's parent.
What is needed to achieve is: after monitoring of a folder, get rid of the locking by the monitoring mechanism. Unfortunately i got no clue why this locking happens. So any idea about possible causes is very appreciated.
What i even tried; directly after a folder rename (with SHFileOperationW): get the its handle using CreateFileW and do a CancelIOEx(FFileHandle, 0) // (0 (or nil?) for to stop _all_ iI/O requests onto this handle). No difference.
ASerge:
There may be a problem in the SHFileOperationW function. Try renaming the directory using the MoveFile function.
d7_2_laz:
Hm, wouldn't have suspected that side, but, after test, with MoveFile basically it did behave the same (already in use within the scenario described).
So i did spend some time to prepare a minimalistic test case, and at least i can say it did reproduce the issue indeed.
Very simple Gui, 2 entry fields representing a parent and a sub folder for to paste in,
and, if valid, one can select parent or child by button(analogous to treenode click) and then trigger a simple rename action on it.
Instrutions are in a memo field. -> project attached
When preparing that code, i came more and more close to the impression that the issue might be due to an inproper thread termination so that the ReadDirectoryChangesW stays sticky on an old folder and hinders to do a rename of the parent after having renamed a child.
Maybe Lazarus or x64 may require a slightly different coding here. But where ..
ASerge:
--- Quote from: d7_2_laz on May 23, 2021, 02:02:18 pm ---
--- End quote ---
After changing in Fldrwatch_buffered.pas
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- EventArray[1] := plocaleventrec(TermEvent.Handle)^.Fhandle; EventArray[2] := plocaleventrec(SuspEvent.Handle)^.Fhandle;to
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- EventArray[1] := THandle(TermEvent.Handle); EventArray[2] := THandle(SuspEvent.Handle);everything works without errors.
Navigation
[0] Message Index
[#] Next page
[*] Previous page