16
16
using System . Threading ;
17
17
using System . Threading . Tasks ;
18
18
using Windows . ApplicationModel . Core ;
19
+ using Windows . Foundation ;
19
20
using Windows . Foundation . Collections ;
20
21
using Windows . Storage ;
21
22
using Windows . Storage . FileProperties ;
@@ -34,8 +35,10 @@ namespace Files.Filesystem
34
35
{
35
36
public class ItemViewModel : INotifyPropertyChanged , IDisposable
36
37
{
37
- private volatile bool IsWatching = false ;
38
+ private volatile bool MustTryToWatchAgain = false ;
39
+ private static SemaphoreSlim semaphoreSlim = new SemaphoreSlim ( 1 , 1 ) ;
38
40
private IntPtr hWatchDir ;
41
+ private IAsyncAction aWatcherAction ;
39
42
public ReadOnlyObservableCollection < ListedItem > FilesAndFolders { get ; }
40
43
public ListedItem CurrentFolder { get ; private set ; }
41
44
public CollectionViewSource viewSource ;
@@ -364,11 +367,16 @@ private void WorkingDirectoryChanged()
364
367
365
368
public void CancelLoadAndClearFiles ( )
366
369
{
367
- var x = CancelIo ( hWatchDir ) ;
368
- CloseHandle ( hWatchDir ) ;
369
- hWatchDir = new IntPtr ( - 1 ) ;
370
- Debug . WriteLine ( "\n \n Watcher task aborted...\n \n " ) ; // Cancel directory item change watcher
371
- IsWatching = false ;
370
+ if ( aWatcherAction != null )
371
+ {
372
+ aWatcherAction ? . Cancel ( ) ;
373
+
374
+ if ( aWatcherAction . Status != AsyncStatus . Started )
375
+ {
376
+ CloseWatcher ( ) ;
377
+ }
378
+ }
379
+
372
380
App . CurrentInstance . NavigationToolbar . CanRefresh = true ;
373
381
if ( IsLoadingItems == false ) { return ; }
374
382
@@ -383,12 +391,6 @@ public void CancelLoadAndClearFiles()
383
391
}
384
392
}
385
393
386
- public void CancelChangeWatcher ( )
387
- {
388
- var x = CancelIo ( hWatchDir ) ;
389
- Debug . WriteLine ( "\n \n Watcher task aborted...\n \n " ) ;
390
- }
391
-
392
394
public void OrderFiles ( )
393
395
{
394
396
if ( _filesAndFolders . Count == 0 )
@@ -632,10 +634,8 @@ public async void RapidAddItemsToCollectionAsync(string path)
632
634
{
633
635
634
636
await EnumerateItemsFromStandardFolder ( path ) ;
635
- if ( ! IsWatching )
636
- {
637
- WatchForDirectoryChanges ( path ) ;
638
- }
637
+ WatchForDirectoryChanges ( path ) ;
638
+
639
639
}
640
640
641
641
if ( FilesAndFolders . Count == 0 )
@@ -667,7 +667,11 @@ public async void RapidAddItemsToCollectionAsync(string path)
667
667
}
668
668
}
669
669
670
- private static SemaphoreSlim semaphoreSlim = new SemaphoreSlim ( 1 , 1 ) ;
670
+ public void CloseWatcher ( )
671
+ {
672
+ CancelIo ( hWatchDir ) ;
673
+ //CloseHandle(hWatchDir);
674
+ }
671
675
672
676
public async Task EnumerateItemsFromSpecialFolder ( string path )
673
677
{
@@ -851,113 +855,108 @@ public async Task EnumerateItemsFromStandardFolder(string path)
851
855
852
856
}
853
857
854
- private async void WatchForDirectoryChanges ( string path )
858
+ private void WatchForDirectoryChanges ( string path )
855
859
{
856
- var uiThreadScheduler = TaskScheduler . FromCurrentSynchronizationContext ( ) ;
857
- Task thrItem = null ;
858
- IsWatching = true ;
860
+
859
861
hWatchDir = CreateFileFromApp ( path , 1 , 1 | 2 | 4 ,
860
862
IntPtr . Zero , 3 , ( uint ) File_Attributes . BackupSemantics | ( uint ) File_Attributes . Overlapped , IntPtr . Zero ) ;
861
863
862
864
byte [ ] buff = new byte [ 4096 ] ;
863
865
864
- await Windows . System . Threading . ThreadPool . RunAsync ( ( x ) =>
865
- {
866
- buff = new byte [ 4096 ] ;
867
- int notifyFilters = FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME ;
866
+ aWatcherAction = Windows . System . Threading . ThreadPool . RunAsync ( ( x ) =>
867
+ {
868
868
869
- OVERLAPPED overlapped = new OVERLAPPED ( ) ;
870
- overlapped . hEvent = CreateEvent ( IntPtr . Zero , false , false , null ) ;
871
- const uint INFINITE = 0xFFFFFFFF ;
869
+ buff = new byte [ 4096 ] ;
870
+ int notifyFilters = FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME ;
872
871
873
- while ( hWatchDir . ToInt64 ( ) != - 1 )
874
- {
875
-
876
- unsafe
877
- {
878
- fixed ( byte * pBuff = buff )
879
- {
880
- ref var notifyInformation = ref Unsafe . As < byte , FILE_NOTIFY_INFORMATION > ( ref buff [ 0 ] ) ;
881
- if ( hWatchDir . ToInt64 ( ) != - 1 )
872
+ OVERLAPPED overlapped = new OVERLAPPED ( ) ;
873
+ overlapped . hEvent = CreateEvent ( IntPtr . Zero , false , false , null ) ;
874
+ const uint INFINITE = 0xFFFFFFFF ;
875
+
876
+ while ( x . Status != AsyncStatus . Canceled )
877
+ {
878
+ unsafe
879
+ {
880
+ fixed ( byte * pBuff = buff )
881
+ {
882
+ ref var notifyInformation = ref Unsafe . As < byte , FILE_NOTIFY_INFORMATION > ( ref buff [ 0 ] ) ;
883
+ if ( x . Status != AsyncStatus . Canceled )
882
884
{
883
885
NativeDirectoryChangesHelper . ReadDirectoryChangesW ( hWatchDir , pBuff ,
884
886
4096 , false ,
885
887
notifyFilters , null ,
886
888
ref overlapped , null ) ;
887
- }
888
- else
889
- {
890
- IsWatching = false ;
891
- return ;
892
- }
893
-
894
- var rc = WaitForSingleObjectEx ( overlapped . hEvent , INFINITE , true ) ;
895
-
896
- const uint FILE_ACTION_ADDED = 0x00000001 ;
897
- const uint FILE_ACTION_REMOVED = 0x00000002 ;
898
- const uint FILE_ACTION_MODIFIED = 0x00000003 ;
899
- const uint FILE_ACTION_RENAMED_OLD_NAME = 0x00000004 ;
900
- const uint FILE_ACTION_RENAMED_NEW_NAME = 0x00000005 ;
901
-
902
- uint offset = 0 ;
903
- ref var notifyInfo = ref Unsafe . As < byte , FILE_NOTIFY_INFORMATION > ( ref buff [ offset ] ) ;
904
- if ( hWatchDir . ToInt64 ( ) == - 1 ) { IsWatching = false ; return ; }
905
-
906
- do
907
- {
908
- notifyInfo = ref Unsafe . As < byte , FILE_NOTIFY_INFORMATION > ( ref buff [ offset ] ) ;
909
- string FileName = null ;
910
- unsafe
911
- {
912
- fixed ( char * name = notifyInfo . FileName )
913
- {
914
- FileName = Path . Combine ( path , new string ( name , 0 , ( int ) notifyInfo . FileNameLength / 2 ) ) ;
915
- }
916
- }
917
-
918
- uint action = notifyInfo . Action ;
919
-
920
- switch ( action )
921
- {
922
- case FILE_ACTION_ADDED :
923
- AddFileOrFolder ( FileName ) ;
924
- Debug . WriteLine ( "File " + FileName + " added to working directory." ) ;
925
- break ;
926
- case FILE_ACTION_REMOVED :
927
- RemoveFileOrFolder ( FilesAndFolders . ToList ( ) . First ( x => x . ItemPath . Equals ( FileName ) ) ) ;
928
- Debug . WriteLine ( "File " + FileName + " removed from working directory." ) ;
929
- break ;
930
- case FILE_ACTION_MODIFIED :
931
- Debug . WriteLine ( "File " + FileName + " had attributes modified in the working directory." ) ;
932
- break ;
933
- case FILE_ACTION_RENAMED_OLD_NAME :
934
- RemoveFileOrFolder ( FilesAndFolders . ToList ( ) . First ( x => x . ItemPath . Equals ( FileName ) ) ) ;
935
- Debug . WriteLine ( "File " + FileName + " will be renamed in the working directory." ) ;
936
- break ;
937
- case FILE_ACTION_RENAMED_NEW_NAME :
938
- AddFileOrFolder ( FileName ) ;
939
- Debug . WriteLine ( "File " + FileName + " was renamed in the working directory." ) ;
940
- break ;
941
- default :
942
- Debug . WriteLine ( "File " + FileName + " performed an action in the working directory." ) ;
943
- break ;
944
- }
945
-
946
- offset += notifyInfo . NextEntryOffset ;
947
-
948
- } while ( notifyInfo . NextEntryOffset != 0 && hWatchDir . ToInt64 ( ) != - 1 ) ;
889
+ }
890
+ else
891
+ {
892
+ return ;
893
+ }
894
+
895
+ if ( x . Status == AsyncStatus . Canceled ) { return ; }
896
+ var rc = WaitForSingleObjectEx ( overlapped . hEvent , INFINITE , true ) ;
897
+
898
+ const uint FILE_ACTION_ADDED = 0x00000001 ;
899
+ const uint FILE_ACTION_REMOVED = 0x00000002 ;
900
+ const uint FILE_ACTION_MODIFIED = 0x00000003 ;
901
+ const uint FILE_ACTION_RENAMED_OLD_NAME = 0x00000004 ;
902
+ const uint FILE_ACTION_RENAMED_NEW_NAME = 0x00000005 ;
903
+
904
+ uint offset = 0 ;
905
+ ref var notifyInfo = ref Unsafe . As < byte , FILE_NOTIFY_INFORMATION > ( ref buff [ offset ] ) ;
906
+ if ( x . Status == AsyncStatus . Canceled ) { return ; }
907
+
908
+ do
909
+ {
910
+ notifyInfo = ref Unsafe . As < byte , FILE_NOTIFY_INFORMATION > ( ref buff [ offset ] ) ;
911
+ string FileName = null ;
912
+ unsafe
913
+ {
914
+ fixed ( char * name = notifyInfo . FileName )
915
+ {
916
+ FileName = Path . Combine ( path , new string ( name , 0 , ( int ) notifyInfo . FileNameLength / 2 ) ) ;
917
+ }
918
+ }
919
+
920
+ uint action = notifyInfo . Action ;
921
+
922
+ switch ( action )
923
+ {
924
+ case FILE_ACTION_ADDED :
925
+ AddFileOrFolder ( FileName ) ;
926
+ Debug . WriteLine ( "File " + FileName + " added to working directory." ) ;
927
+ break ;
928
+ case FILE_ACTION_REMOVED :
929
+ RemoveFileOrFolder ( FilesAndFolders . ToList ( ) . First ( x => x . ItemPath . Equals ( FileName ) ) ) ;
930
+ Debug . WriteLine ( "File " + FileName + " removed from working directory." ) ;
931
+ break ;
932
+ case FILE_ACTION_MODIFIED :
933
+ Debug . WriteLine ( "File " + FileName + " had attributes modified in the working directory." ) ;
934
+ break ;
935
+ case FILE_ACTION_RENAMED_OLD_NAME :
936
+ RemoveFileOrFolder ( FilesAndFolders . ToList ( ) . First ( x => x . ItemPath . Equals ( FileName ) ) ) ;
937
+ Debug . WriteLine ( "File " + FileName + " will be renamed in the working directory." ) ;
938
+ break ;
939
+ case FILE_ACTION_RENAMED_NEW_NAME :
940
+ AddFileOrFolder ( FileName ) ;
941
+ Debug . WriteLine ( "File " + FileName + " was renamed in the working directory." ) ;
942
+ break ;
943
+ default :
944
+ Debug . WriteLine ( "File " + FileName + " performed an action in the working directory." ) ;
945
+ break ;
946
+ }
947
+
948
+ offset += notifyInfo . NextEntryOffset ;
949
+
950
+ } while ( notifyInfo . NextEntryOffset != 0 && x . Status != AsyncStatus . Canceled ) ;
949
951
950
952
//ResetEvent(overlapped.hEvent);
951
953
Debug . WriteLine ( "\n \n Task running...\n \n " ) ;
952
- }
953
- }
954
- }
955
- } ) ;
954
+ }
955
+ }
956
+ }
957
+ } ) ;
956
958
957
959
Debug . WriteLine ( "\n \n Task exiting...\n \n " ) ;
958
-
959
- IsWatching = false ;
960
-
961
960
}
962
961
963
962
public void AddFileOrFolder ( ListedItem item )
0 commit comments