Condividi tramite


Tenere traccia in background delle modifiche al file system

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.
  • Spostamento di file e cartelle 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

Il rilevatore delle modifiche viene implementato nel sistema come un buffer circolare per memorizzare le ultime N operazioni 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 è interessata a rilevare le modifiche di una determinata libreria. A tale scopo, tramite la chiamata del metodo Enable sul tracciatore 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 ulteriori dettagli, consultare autorizzazioni di accesso ai file.
  • Abilita è thread-safe, non reimposta il puntatore e può essere chiamato tante volte quanto si desidera (più avanti).

Abilitazione di un tracker 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 registrarsi per essere attivate ogni volta che c'è un cambiamento, tramite la registrazione all'evento StorageLibraryChangedTrigger .

Modifiche che vengono aggiunte al tracciamento delle modifiche senza che l'app le legga

Leggere le modifiche

L'app può quindi controllare le modifiche attraverso il tracciatore di modifiche e ricevere un elenco delle modifiche dall'ultima volta che l'ha verificato. Il codice seguente mostra come ottenere un elenco di modifiche dallo strumento di monitoraggio 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 utente o nel database in base alle esigenze.

Lettura delle modifiche dal tracciatore di modifiche in un database dell'app

Suggerimento

La seconda chiamata ad abilitare serve a difendersi da una condizione di competizione se l'utente aggiunge un'altra cartella alla raccolta mentre la tua app sta leggendo le modifiche. Senza la chiamata aggiuntiva a Abilita il codice avrà esito negativo con ecSearchFolderScopeViolation (0x80070490) se l'utente sta modificando le cartelle nella 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 in modo che non vengano mai più visualizzate

L'app, d'ora in poi, riceverà nuove modifiche solo quando leggerà il tracker dei cambiamenti.

  • Se sono state apportate modifiche tra la chiamata ReadBatchAsync e AcceptChangesAsync, il puntatore verrà avanzato solo fino alla modifica più recente vista dall'app. Queste altre modifiche saranno ancora disponibili alla successiva chiamata 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 tracker delle modifiche per contenere tutte le operazioni che avvengono nel sistema fino a quando l'applicazione non riesce a leggerle, è facile immaginare uno scenario in cui l'app non legge le modifiche prima che il buffer circolare non si sovrascriva da solo. In particolare se l'utente sta ripristinando i dati da un backup o sincronizzando una grande raccolta di immagini dallo smartphone.

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. La migliore azione da intraprendere è quella di riesaminare la libreria, perché qualsiasi informazione dal tracker sarà incompleta.
  • Lo strumento di rilevamento delle modifiche non restituirà altre modifiche fino a quando non viene chiamato Reimposta. Dopo che l'app richiama la funzione di reset, il puntatore verrà spostato alla modifica più recente e il rilevamento riprenderà normalmente.

Dovrebbe essere raro che si verifichino questi casi, ma negli scenari in cui l'utente sta spostando un numero elevato di file sul disco, non si vuole 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 riportate nel rilevamento modifiche. Le cartelle principali della libreria possono essere trovate usando la proprietà Folders.
  • L'aggiunta o la rimozione di cartelle radice da una StorageLibrary (tramite RequestAddFolderAsync e RequestRemoveFolderAsync) non creerà una voce nel tracciatore 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à presente viene aggiunta alla raccolta, non verrà generata una ricevuta di modifica o registrazioni del tracker delle modifiche. Eventuali modifiche successive ai discendenti di tale cartella genereranno notifiche e modifiche alle voci di rilevamento.

Chiamata al metodo Enable

Le applicazioni 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();
}