Condividi tramite


Tenere traccia delle modifiche al file system in secondo piano

API Importanti

La classe StorageLibraryChangeTracker consente alle app di tenere traccia delle modifiche nei file e nelle cartelle man mano che gli utenti li spostano nel sistema. Usando la classe StorageLibraryChangeTracker, un'app può tenere traccia:

  • Operazioni di file che includono aggiunta, eliminazione, modifica.
  • Operazioni di cartella, ad esempio rinomina ed eliminazioni.
  • File e cartelle vengono spostati sull'unità.

Usare questa guida per apprendere il modello di programmazione per l'uso dello strumento di rilevamento delle modifiche, visualizzare il codice di esempio e comprendere i diversi tipi di operazioni di file rilevati da StorageLibraryChangeTracker.

StorageLibraryChangeTracker funziona per le librerie utente o per qualsiasi cartella nel computer locale. Sono incluse unità secondarie o unità rimovibili, ma non unità NAS o unità di rete.

Uso dello strumento di rilevamento delle modifiche

Lo strumento di rilevamento delle modifiche viene implementato nel sistema come buffer circolare che archivia le ultime operazioni N del file system. Le app possono leggere le modifiche dal buffer e quindi elaborarle nelle proprie esperienze. Una volta completata la modifica, l'app contrassegna le modifiche come elaborate e non le visualizzerà mai più.

Per usare lo strumento di rilevamento delle modifiche in una cartella, seguire questa procedura:

  1. Abilitare il rilevamento delle modifiche per la cartella.
  2. Attendere le modifiche.
  3. Leggere le modifiche.
  4. Accettare le modifiche.

Le sezioni successive illustrano ognuno dei passaggi con alcuni esempi di codice. L'esempio di codice completo viene fornito alla fine dell'articolo.

Abilitare lo strumento di rilevamento delle modifiche

La prima cosa che l'app deve fare è indicare al sistema che è interessato al rilevamento delle modifiche una determinata libreria. Lo fa chiamando il metodo Enable nel rilevamento delle modifiche per la libreria di interesse.

StorageLibrary videosLib = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
StorageLibraryChangeTracker videoTracker = videosLib.ChangeTracker;
videoTracker.Enable();

Alcune note importanti:

  • Assicurarsi che l'app disponga dell'autorizzazione per la libreria corretta nel manifesto prima di creare l'oggetto StorageLibrary . Per altri dettagli, vedere Autorizzazioni di accesso ai file .
  • L'abilitazione è thread-safe, non reimposta il puntatore e può essere chiamato il maggior numero di volte desiderato (più avanti).

Abilitazione di un tracciatore di modifiche vuoto

Attendere le modifiche

Dopo l'inizializzazione dello strumento di rilevamento modifiche, inizierà a registrare tutte le operazioni che si verificano all'interno di una libreria, anche se l'app non è in esecuzione. Le app possono essere registrate per essere attivate ogni volta che si verifica una modifica registrando per l'evento StorageLibraryChangedTrigger .

Modifiche aggiunte allo strumento di rilevamento delle modifiche senza che l'app le legge

Leggere le modifiche

L'app può quindi eseguire il polling delle modifiche dal tracker delle modifiche e ricevere un elenco delle modifiche dall'ultima volta che ha controllato. Il codice seguente mostra come ottenere un elenco di modifiche dal tracker delle modifiche.

StorageLibrary videosLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
videosLibrary.ChangeTracker.Enable();
StorageLibraryChangeReader videoChangeReader = videosLibrary.ChangeTracker.GetChangeReader();
IReadOnlyList changeSet = await changeReader.ReadBatchAsync();

L'app è quindi responsabile dell'elaborazione delle modifiche nell'esperienza o nel database in base alle esigenze.

Lettura delle modifiche dal tracker delle modifiche nel database dell'app

Suggerimento

La seconda chiamata ad abilitare consiste nel difendersi da una condizione di concorrenza se l'utente aggiunge un'altra cartella alla raccolta mentre l'applicazione rileva le modifiche. Senza la chiamata aggiuntiva a "Enable", il codice fallirà con ecSearchFolderScopeViolation (0x80070490) se l'utente sta cambiando le cartelle nella propria libreria.

Accettare le modifiche

Al termine dell'elaborazione delle modifiche, l'app dovrebbe indicare al sistema di non visualizzare mai più tali modifiche chiamando il metodo AcceptChangesAsync .

await changeReader.AcceptChangesAsync();

Contrassegnare le modifiche come lette affinché non siano mai più visualizzate

In futuro, l'app riceverà nuove modifiche soltanto quando legge il registro delle modifiche.

  • Se sono state apportate modifiche tra la chiamata a ReadBatchAsync e AcceptChangesAsync, il puntatore sarà avanzato solo alla modifica più recente rilevata dall'app. Le altre modifiche saranno ancora disponibili alla successiva chiamata a ReadBatchAsync.
  • Se non si accettano le modifiche, il sistema restituirà lo stesso set di modifiche la volta successiva che l'app chiama ReadBatchAsync.

Informazioni importanti da ricordare

Quando si usa lo strumento di rilevamento delle modifiche, ci sono alcuni aspetti da tenere presente per assicurarsi che tutto funzioni correttamente.

Sovraccarichi del buffer

Anche se proviamo a riservare spazio sufficiente nel rilevamento modifiche per contenere tutte le operazioni eseguite nel sistema fino a quando l'app non può leggerle, è molto facile immaginare uno scenario in cui l'app non legge le modifiche prima che il buffer circolare sovrascriva se stesso. In particolare se l'utente sta ripristinando i dati da un backup o sincronizzando una grande raccolta di immagini dal telefono della fotocamera.

In questo caso, ReadBatchAsync restituirà il codice di errore StorageLibraryChangeType.ChangeTrackingLost. Se l'app riceve questo codice di errore, significa un paio di cose:

  • Il buffer si è sovrascritto dall'ultima volta che l'hai esaminato. Il migliore approccio è quello di rieseguire la scansione della libreria, perché qualsiasi informazione proveniente dal tracker sarà incompleta.
  • Lo strumento di rilevamento delle modifiche non restituirà altre modifiche fino a quando non si chiama Reimposta. Dopo la reimpostazione delle chiamate dell'app, il puntatore verrà spostato nella modifica più recente e il rilevamento riprenderà normalmente.

Dovrebbe essere raro che si verifichino questi casi, ma negli scenari in cui l'utente sposta un numero elevato di file sul disco, non vogliamo che lo strumento di rilevamento delle modifiche si espanda e occupi troppo spazio di archiviazione. Ciò dovrebbe consentire alle app di reagire alle operazioni massicce del file system, senza danneggiare l'esperienza dei clienti in Windows.

Modifiche a un oggetto StorageLibrary

La classe StorageLibrary esiste come gruppo virtuale di cartelle radice che contengono altre cartelle. Per riconciliare questo problema con uno strumento di rilevamento delle modifiche del file system, sono state effettuate le seguenti scelte:

  • Tutte le modifiche apportate ai discendenti delle cartelle della libreria radice saranno visualizzate nel tracciatore di modifiche. Le cartelle della libreria radice sono disponibili usando la proprietà Folders .
  • L'aggiunta o la rimozione di cartelle radice da un oggetto StorageLibrary (tramite RequestAddFolderAsync e RequestRemoveFolderAsync) non creerà una voce nel tracker delle modifiche. Queste modifiche possono essere rilevate tramite l'evento DefinitionChanged o enumerando le cartelle radice nella libreria usando la proprietà Folders .
  • Se una cartella con contenuto già al suo interno viene aggiunta alla raccolta, non verranno generate né una notifica di modifica né voci del rilevatore di modifiche. Eventuali modifiche successive ai discendenti di tale cartella genereranno notifiche e modifiche alle voci di rilevamento.

Chiamata al metodo Enable

Le app devono chiamare Abilita non appena iniziano a tenere traccia del file system e prima di ogni enumerazione delle modifiche. In questo modo si garantisce che tutte le modifiche verranno acquisite dallo strumento di rilevamento delle modifiche.

Mettere tutto insieme

Di seguito è riportato tutto il codice usato per registrare le modifiche dalla raccolta video e iniziare a eseguire il pull delle modifiche dal rilevamento delle modifiche.

private async void EnableChangeTracker()
{
    StorageLibrary videosLib = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
    StorageLibraryChangeTracker videoTracker = videosLib.ChangeTracker;
    videoTracker.Enable();
}

private async void GetChanges()
{
    StorageLibrary videosLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
    videosLibrary.ChangeTracker.Enable();
    StorageLibraryChangeReader videoChangeReader = videosLibrary.ChangeTracker.GetChangeReader();
    IReadOnlyList changeSet = await changeReader.ReadBatchAsync();


    //Below this line is for the blog post. Above the line is for the magazine
    foreach (StorageLibraryChange change in changeSet)
    {
        if (change.ChangeType == StorageLibraryChangeType.ChangeTrackingLost)
        {
            //We are in trouble. Nothing else is going to be valid.
            log("Resetting the change tracker");
            videosLibrary.ChangeTracker.Reset();
            return;
        }
        if (change.IsOfType(StorageItemTypes.Folder))
        {
            await HandleFileChange(change);
        }
        else if (change.IsOfType(StorageItemTypes.File))
        {
            await HandleFolderChange(change);
        }
        else if (change.IsOfType(StorageItemTypes.None))
        {
            if (change.ChangeType == StorageLibraryChangeType.Deleted)
            {
                RemoveItemFromDB(change.Path);
            }
        }
    }
    await changeReader.AcceptChangesAsync();
}