Trasferimenti in background

Usare l'API di trasferimento in background per copiare file in modo affidabile in rete. L'API di trasferimento in background fornisce funzionalità avanzate di caricamento e download eseguite in background durante la sospensione dell'app, che persistono oltre la chiusura dell'app. L'API monitora lo stato della rete e sospende e riprende automaticamente i trasferimenti quando la connettività viene persa. I trasferimenti sono anche compatibili con Data Sense e Battery Sense, il che significa che l'attività di download si adatta in base allo stato corrente della connettività e della batteria del dispositivo. L'API è ideale per caricare e scaricare file di grandi dimensioni usando HTTP(S). Anche FTP è supportato, ma solo per i download.

Il trasferimento in background viene eseguito separatamente dall'app chiamante ed è progettato principalmente per operazioni di trasferimento a lungo termine per risorse come video, musica e immagini di grandi dimensioni. Per questi scenari, l'uso di Trasferimento in background è essenziale perché i download continuano a progredire anche quando l'app viene sospesa.

Se si scaricano risorse di piccole dimensioni che potrebbero essere completate rapidamente, è consigliabile usare API HttpClient anziché trasferimento in background.

Uso di Windows.Networking.BackgroundTransfer

Come funziona la funzionalità Trasferimento in background?

Quando un'app usa il trasferimento in background per avviare un trasferimento, la richiesta viene configurata e inizializzata usando BackgroundDownloader o BackgroundUploader oggetti classe. Ogni operazione di trasferimento viene gestita singolarmente dal sistema e separata dall'app chiamante. Le informazioni sullo stato di avanzamento sono disponibili se si vuole assegnare lo stato all'utente nell'interfaccia utente dell'app e l’app può sospendere, riprendere, annullare o persino leggere dai dati durante l'esecuzione del trasferimento. Il modo in cui i trasferimenti vengono gestiti dal sistema promuove l'utilizzo intelligente dell'alimentazione e impedisce problemi che possono verificarsi quando un'app connessa rileva eventi come sospensione, terminazione o modifiche improvvise dello stato di rete.

Nota

A causa dei vincoli delle risorse per ogni app, un'app non deve avere più di 200 trasferimenti (DownloadOperations + UploadOperations) in un determinato momento. Il superamento di questo limite potrebbe impostare uno stato irreversibile per la coda di trasferimento dell'app.

Quando viene avviata un'applicazione, è necessario chiamare AttachAsync in tutti gli oggetti esistenti DownloadOperation e UploadOperation. Questa operazione non causerà la perdita di trasferimenti già completati e renderà infine impossibile usare la funzionalità di trasferimento in background.

Esecuzione di richieste di file autenticate con trasferimento in background

Trasferimento in background fornisce metodi che supportano le credenziali di base del server e del proxy, i cookie e l'uso di intestazioni HTTP personalizzate (tramite SetRequestHeader) per ogni operazione di trasferimento.

In che modo questa funzionalità si adatta alle modifiche dello stato della rete o agli arresti imprevisti?

La funzionalità Trasferimento in background mantiene un'esperienza coerente per ogni operazione di trasferimento quando si verificano modifiche allo stato della rete, sfruttando in modo intelligente le informazioni sullo stato della connettività e del piano dati del gestore telefonico fornite dalla funzionalità connettività. Per definire il comportamento per diversi scenari di rete, un'app imposta un criterio di costo per ogni operazione usando i valori definiti da BackgroundTransferCostPolicy.

Ad esempio, i criteri di costo definiti per un'operazione possono indicare che l'operazione deve essere sospesa automaticamente quando il dispositivo usa una rete a consumo. Il trasferimento viene quindi ripreso automaticamente (o riavviato) quando è stata stabilita una connessione a una rete "senza restrizioni". Per altre informazioni sulla definizione delle reti in base al costo, vedere NetworkCostType.

Sebbene la funzionalità Trasferimento in background disponga di meccanismi specifici per la gestione delle modifiche dello stato della rete, esistono altre considerazioni generali sulla connettività per le app connesse alla rete. Per altre informazioni, leggere Sfruttare le informazioni di connessione di rete disponibili.

Nota Per le app eseguite su dispositivi mobili, sono disponibili funzionalità che consentono all’utente di monitorare e limitare la quantità di dati trasferiti in base al tipo di connessione, allo stato di roaming e al piano dati dell’utente. Per questo motivo, i trasferimenti in background possono essere sospesi sul telefono anche quando il BackgroundTransferCostPolicy indica che il trasferimento deve continuare.

La tabella seguente indica quando i trasferimenti in background sono consentiti sul telefono per ogni Valore backgroundTransferCostPolicy, dato lo stato corrente del telefono. È possibile usare la classe ConnectionCost per determinare lo stato corrente del telefono.

Stato dispositivo UnrestrictedOnly Default Sempre
Connesso al Wi-Fi Consenti Consenti Consenti
Connessione a consumo, non roaming, al di sotto del limite di dati, per rimanere al di sotto del limite Nega Consenti Consenti
Connessione a consumo, non roaming, al di sotto del limite di dati, su traccia per superare il limite Nega Nega Consenti
Connessione a consumo, roaming, al di sotto del limite di dati Nega Nega Consenti
Connessione a consumo, oltre il limite di dati. Questo stato si verifica solo quando l'utente abilita "Limita i dati in background nell'interfaccia utente di Data Sense. Nega Nega Nega

Caricamento di file

Quando si usa trasferimento in background esiste un caricamento come UploadOperation che espone diversi metodi di controllo usati per riavviare o annullare l'operazione. Gli eventi dell'app, ad esempio la sospensione o la chiusura, e le modifiche alla connettività vengono gestiti automaticamente dal sistema per ogni UploadOperation. I caricamenti continueranno durante i periodi di sospensione dell'app oppure verranno sospesi e mantenuti oltre la chiusura dell'app. Inoltre, l'impostazione della proprietà CostPolicy indicherà se l'app avvierà o meno i caricamenti mentre viene usata una rete a consumo per la connettività Internet.

Gli esempi seguenti illustrano la creazione e l'inizializzazione di un caricamento di base e come enumerare e reintrodurre le operazioni persistenti da una sessione precedente dell'app.

Caricare un singolo file

La creazione di un caricamento inizia con BackgroundUploader. Questa classe viene usata per fornire i metodi che consentono all'app di configurare il caricamento prima di creare il risultato UploadOperation. Nell'esempio seguente viene illustrato come eseguire questa operazione con i URI necessari e oggetti StorageFile.

Identificare il file e la destinazione per il caricamento

Prima di iniziare con la creazione di un UploadOperation, è prima necessario identificare l'URI del percorso in cui caricare e il file in cui verrà caricato. Nell'esempio seguente il valore uriString viene popolato usando una stringa dall'input dell'interfaccia utente e il valore file usando l'oggetto StorageFile restituito da un'operazione PickSingleFileAsync.

function uploadFile() {
    var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
    filePicker.fileTypeFilter.replaceAll(["*"]);

    filePicker.pickSingleFileAsync().then(function (file) {
        if (!file) {
            printLog("No file selected");
            return;
        }

        var upload = new UploadOp();
        var uriString = document.getElementById("serverAddressField").value;
        upload.start(uriString, file);

        // Store the upload operation in the uploadOps array.
        uploadOperations.push(upload);
    });
}

Creare e inizializzare l'operazione di caricamento

Nel passaggio precedente i valori uriString e file vengono passati a un'istanza dell'esempio successivo, UploadOp, in cui vengono usati per configurare e avviare la nuova operazione di caricamento. Prima di tutto, uriString viene analizzato per creare l'oggetto Uri necessario.

Successivamente, le proprietà dell' StorageFile (file) vengono usate da BackgroundUploader per popolare l'intestazione della richiesta e impostare la proprietà SourceFile con l'oggetto StorageFile. Il metodo SetRequestHeader viene quindi chiamato per inserire il nome del file, fornito come stringa e la proprietà StorageFile.Name.

Infine, BackgroundUploader crea l'UploadOperation (caricare).

function UploadOp() {
    var upload = null;
    var promise = null;

    this.start = function (uriString, file) {
        try {
        
            var uri = new Windows.Foundation.Uri(uriString);
            var uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();

            // Set a header, so the server can save the file (this is specific to the sample server).
            uploader.setRequestHeader("Filename", file.name);

            // Create a new upload operation.
            upload = uploader.createUpload(uri, file);

            // Start the upload and persist the promise to be able to cancel the upload.
            promise = upload.startAsync().then(complete, error, progress);
        } catch (err) {
            displayError(err);
        }
    };
    // On application activation, reassign callbacks for a upload
    // operation persisted from previous application state.
    this.load = function (loadedUpload) {
        try {
            upload = loadedUpload;
            promise = upload.attachAsync().then(complete, error, progress);
        } catch (err) {
            displayError(err);
        }
    };
}

Si noti che le chiamate al metodo asincrono definite usando le promesse JavaScript. Esaminare una riga dell'ultimo esempio:

promise = upload.startAsync().then(complete, error, progress);

La chiamata al metodo asincrono è seguita da un'thenistruzione che indica i metodi, definiti dall'app, che vengono chiamati quando viene restituito un risultato dalla chiamata al metodo asincrono. Per altre informazioni su questo modello di programmazione, vedere Programmazione asincrona in JavaScript usando promesse.

Caricamento di più file

Identificare i file e la destinazione per il caricamento

In uno scenario che coinvolge più file trasferiti con un singolo UploadOperation, il processo inizia come in genere avvierà fornendo prima l'URI di destinazione e le informazioni sul file locale necessarie. Analogamente all'esempio nella sezione precedente, l'URI viene fornito come stringa dall'utente finale e FileOpenPicker può essere usato per fornire la possibilità di indicare anche i file tramite l'interfaccia utente. Tuttavia, in questo scenario l'app deve invece chiamare il metodo PickMultipleFilesAsync per abilitare la selezione di più file tramite l'interfaccia utente.

function uploadFiles() {
       var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
       filePicker.fileTypeFilter.replaceAll(["*"]);

       filePicker.pickMultipleFilesAsync().then(function (files) {
          if (files === 0) {
             printLog("No file selected");
                return;
          }

          var upload = new UploadOperation();
          var uriString = document.getElementById("serverAddressField").value;
          upload.startMultipart(uriString, files);

          // Persist the upload operation in the global array.
          uploadOperations.push(upload);
       });
    }

Creare oggetti per i parametri forniti

I due esempi successivi usano il codice contenuto in un singolo metodo di esempio, startMultipart, che è stato chiamato alla fine dell'ultimo passaggio. Ai fini dell'istruzione il codice nel metodo che crea una matrice di oggetti BackgroundTransferContentPart è stato suddiviso dal codice che crea il risultato UploadOperation.

Prima di tutto, la stringa URI fornita dall'utente viene inizializzata come URI. Successivamente, la matrice di oggetti IStorageFile (file) passata a questo metodo viene iterata, ogni oggetto viene usato per creare un nuovo oggetto BackgroundTransferContentPart che viene quindi inserito nella matrice contentParts.

    upload.startMultipart = function (uriString, files) {
        try {
            var uri = new Windows.Foundation.Uri(uriString);
            var uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();

            var contentParts = [];
            files.forEach(function (file, index) {
                var part = new Windows.Networking.BackgroundTransfer.BackgroundTransferContentPart("File" + index, file.name);
                part.setFile(file);
                contentParts.push(part);
            });

Creare e inizializzare l'operazione di caricamento in più parti

Con la matrice contentParts popolata con tutti gli oggetti BackgroundTransferContentPart che rappresentano ogni IStorageFile per il caricamento, è possibile chiamare CreateUploadAsync usando l’Uri per indicare dove verrà inviata la richiesta.

        // Create a new upload operation.
            uploader.createUploadAsync(uri, contentParts).then(function (uploadOperation) {

               // Start the upload and persist the promise to be able to cancel the upload.
               upload = uploadOperation;
               promise = uploadOperation.startAsync().then(complete, error, progress);
            });

         } catch (err) {
             displayError(err);
         }
     };

Riavvio delle operazioni di caricamento interrotte

Al termine o all'annullamento di un UploadOperation, vengono rilasciate tutte le risorse di sistema associate. Tuttavia, se l'app viene terminata prima che si verifichi una di queste operazioni, tutte le operazioni attive vengono sospese e le risorse associate a ogni elemento rimangono occupate. Se queste operazioni non vengono enumerate e introdotte nuovamente alla sessione successiva dell'app, non verranno completate e continueranno a occupare le risorse del dispositivo.

  1. Prima di definire la funzione che enumera le operazioni persistenti, è necessario creare una matrice che conterrà l' UploadOperation oggetti restituiti:

    var uploadOperations = [];
    
  2. Successivamente si definisce la funzione che enumera le operazioni persistenti e le archivia nella matrice. Si noti che il metodo di caricamento chiamato per assegnare nuovamente i callback all'UploadOperation, in caso di persistenza tramite la terminazione dell'app, si trova nella classe UploadOp definita più avanti in questa sezione.

    function Windows.Networking.BackgroundTransfer.BackgroundUploader.getCurrentUploadsAsync() {
        .then(function (uploads) {
            for (var i = 0; i < uploads.size; i++) {
                var upload = new UploadOp();
                upload.load(uploads[i]);
                uploadOperations.push(upload);
            }
        }
    };
    

Download di file

Quando si usa trasferimento in background, ogni download esiste come DownloadOperation che espone diversi metodi di controllo usati per sospendere, riprendere, riavviare e annullare l'operazione. Gli eventi dell'app, ad esempio la sospensione o la chiusura, e le modifiche alla connettività vengono gestiti automaticamente dal sistema per ogni DownloadOperation. I download continueranno durante i periodi di sospensione dell'app oppure verranno sospesi e mantenuti oltre la chiusura dell'app. Per gli scenari di rete mobile, l'impostazione della proprietà CostPolicy indicherà se l'app inizierà o continuerà a scaricare mentre viene usata una rete a consumo per la connettività Internet.

Se si scaricano risorse di piccole dimensioni che potrebbero essere completate rapidamente, è consigliabile usare API HttpClient anziché trasferimento in background.

Gli esempi seguenti illustrano la creazione e l'inizializzazione di un scaricamento di base e come enumerare e reintrodurre le operazioni persistenti da una sessione precedente dell'app.

Configurare e avviare il download di un file di trasferimento in background

Nell'esempio seguente viene illustrato come utilizzare le stringhe che rappresentano un URI e un nome di file per creare un oggetto URI e lo StorageFile che conterrà il file richiesto. In questo esempio il nuovo file viene inserito automaticamente in un percorso predefinito. In alternativa, FileSavePicker può essere usato per indicare dove salvare il file nel dispositivo. Si noti che il metodo di caricamento chiamato per assegnare nuovamente i callback all'UploadOperation, in caso di persistenza tramite la terminazione dell'app, si trova nella classe UploadOp definita più avanti in questa sezione.

function DownloadOp() {
    var download = null;
    var promise = null;
    var imageStream = null;

    this.start = function (uriString, fileName) {
        try {
            // Asynchronously create the file in the pictures folder.
            Windows.Storage.KnownFolders.picturesLibrary.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.generateUniqueName).done(function (newFile) {
                var uri = Windows.Foundation.Uri(uriString);
                var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();

                // Create a new download operation.
                download = downloader.createDownload(uri, newFile);

                // Start the download and persist the promise to be able to cancel the download.
                promise = download.startAsync().then(complete, error, progress);
            }, error);
        } catch (err) {
            displayException(err);
        }
    };
    // On application activation, reassign callbacks for a download
    // operation persisted from previous application state.
    this.load = function (loadedDownload) {
        try {
            download = loadedDownload;
            printLog("Found download: " + download.guid + " from previous application run.<br\>");
            promise = download.attachAsync().then(complete, error, progress);
        } catch (err) {
            displayException(err);
        }
    };
}

Si noti che le chiamate al metodo asincrono definite usando le promesse JavaScript. Esaminando la riga 17 dell'esempio di codice precedente:

promise = download.startAsync().then(complete, error, progress);

La chiamata al metodo asincrono è seguita da un'istruzione then che indica i metodi, definiti dall'app, che vengono chiamati quando viene restituito un risultato dalla chiamata al metodo asincrono. Per altre informazioni su questo modello di programmazione, vedere Programmazione asincrona in JavaScript usando promesse.

Aggiunta di metodi di controllo delle operazioni aggiuntivi

Il livello di controllo può essere aumentato implementando altri metodi DownloadOperation. Ad esempio, l'aggiunta del codice seguente all'esempio precedente introduce la possibilità di annullare il download.

// Cancel download.
this.cancel = function () {
    try {
        if (promise) {
            promise.cancel();
            promise = null;
            printLog("Canceling download: " + download.guid + "<br\>");
            if (imageStream) {
                imageStream.close();
            }
        }
        else {
            printLog("Download " + download.guid + " already canceled.<br\>");
        }
    } catch (err) {
        displayException(err);
    }
};

Enumerazione delle operazioni persistenti all'avvio

Al termine o all'annullamento di un DownloadOperation, vengono rilasciate tutte le risorse di sistema associate. Tuttavia, se l'app viene terminata prima che si verifichi uno di questi eventi, i download verranno sospesi e resi persistenti in background. Gli esempi seguenti illustrano come introdurre nuovamente i download salvati in modo permanente in una nuova sessione dell'app.

  1. Prima di definire la funzione che enumera le operazioni persistenti, è necessario creare una matrice che conterrà l' DownloadOperation oggetti restituiti:

    var downloadOps = [];
    
  2. Successivamente si definisce la funzione che enumera le operazioni persistenti e le archivia nella matrice. Si noti che il metodo di caricamento chiamato per riassegnare i callback per un persistente DownloadOperation si trova nell'esempio DownloadOp definito più avanti in questa sezione.

    // Enumerate outstanding downloads.
    Windows.Networking.BackgroundTransfer.BackgroundDownloader.getCurrentDownloadsAsync().done(function (downloads) {
    
        for (var i = 0; i < downloads.size; i++) {
            var download = new DownloadOp();
            download.load(downloads[i]);
            downloadOps.push(download);
        }
    });
    
  3. È ora possibile usare l'elenco popolato per riavviare le operazioni in sospeso.

Post-elaborazione

Una nuova funzionalità di Windows 10 è la possibilità di eseguire il codice dell'applicazione al termine di un trasferimento in background anche quando l'app non è in esecuzione. Ad esempio, l'app potrebbe voler aggiornare un elenco di film disponibili al termine del download di un film, invece di fare in modo che l'app analizzi nuovi film ogni volta che viene avviato. In alternativa, l'app potrebbe voler gestire un trasferimento di file non riuscito riprovando a usare un server o una porta diversa. La post-elaborazione viene richiamata sia per i trasferimenti riusciti che per i trasferimenti non riusciti, quindi è possibile usarla per implementare la gestione degli errori personalizzata e la logica di ripetizione dei tentativi.

La post-elaborazione usa l'infrastruttura di attività in background esistente. Creare un'attività in background e associarla ai trasferimenti prima di avviare i trasferimenti. I trasferimenti vengono quindi eseguiti in background e, al termine, viene chiamata l'attività in background per eseguire la post-elaborazione.

La post-elaborazione usa una nuova classe, BackgroundTransferCompletionGroup. Questa classe è simile alla backgroundTransferGroup esistente in quanto consente di raggruppare i trasferimenti in background insieme, ma BackgroundTransferCompletionGroup aggiunge la possibilità di designare un'attività in background da eseguire al termine del trasferimento.

Si avvia un trasferimento in background con post-elaborazione come indicato di seguito.

  1. Creare un oggetto BackgroundTransferCompletionGroup. Creare quindi un oggetto BackgroundTaskBuilder. Impostare la proprietà Trigger dell’oggetto generatore sull’oggetto gruppo di completamento e la proprietà TaskEngtyPoint del generatore sul punto di ingresso dell’attività in background da eseguire al termine del trasferimento. Infine, chiamare il metodo BackgroundTaskBuilder.Register per registrare l'attività in background. Si noti che molti gruppi di completamento possono condividere un punto di ingresso dell'attività in background, ma è possibile avere un solo gruppo di completamento per ogni registrazione dell'attività in background.
var completionGroup = new BackgroundTransferCompletionGroup();
BackgroundTaskBuilder builder = new BackgroundTaskBuilder();

builder.Name = "MyDownloadProcessingTask";
builder.SetTrigger(completionGroup.Trigger);
builder.TaskEntryPoint = "Tasks.BackgroundDownloadProcessingTask";

BackgroundTaskRegistration downloadProcessingTask = builder.Register();
  1. Successivamente si associano i trasferimenti in background al gruppo di completamento. Dopo aver creato tutti i trasferimenti, abilitare il gruppo di completamento.
BackgroundDownloader downloader = new BackgroundDownloader(completionGroup);
DownloadOperation download = downloader.CreateDownload(uri, file);
Task<DownloadOperation> startTask = download.StartAsync().AsTask();

// App still sees the normal completion path
startTask.ContinueWith(ForegroundCompletionHandler);

// Do not enable the CompletionGroup until after all downloads are created.
downloader.CompletionGroup.Enable();
  1. Il codice nell'attività in background estrae l'elenco di operazioni dai dettagli del trigger e il codice può quindi esaminare i dettagli per ogni operazione ed eseguire la post-elaborazione appropriata per ogni operazione.
public class BackgroundDownloadProcessingTask : IBackgroundTask
{
    public async void Run(IBackgroundTaskInstance taskInstance)
    {
    var details = (BackgroundTransferCompletionGroupTriggerDetails)taskInstance.TriggerDetails;
    IReadOnlyList<DownloadOperation> downloads = details.Downloads;

    // Do post-processing on each finished operation in the list of downloads
    }
}

L'attività di post-elaborazione è un'attività in background regolare. Fa parte del pool di tutte le attività in background ed è soggetto allo stesso criterio di gestione delle risorse di tutte le attività in background.

Si noti inoltre che la post-elaborazione non sostituisce i gestori di completamento in primo piano. Se l'app definisce un gestore di completamento in primo piano e l'app viene eseguita al termine del trasferimento del file, verrà chiamato sia il gestore di completamento in primo piano sia il gestore di completamento in background. L'ordine in cui vengono chiamate le attività in primo piano e in background non è garantito. Se si definiscono entrambi, è necessario assicurarsi che le due attività funzionino correttamente e non interferiscano tra loro se vengono eseguite contemporaneamente.

Timeout test

Esistono due scenari di timeout di connessione principali da prendere in considerazione:

  • Quando si stabilisce una nuova connessione per un trasferimento, la richiesta di connessione viene interrotta se non viene stabilita entro cinque minuti.

  • Dopo aver stabilito una connessione, viene interrotto un messaggio di richiesta HTTP che non ha ricevuto una risposta entro due minuti.

NotaIn entrambi gli scenari, e posto sia disponibile la connettività Internet, funzionalità Trasferimento in background effettuerà altri tre tentativi di inviare la richiesta. Nel caso in cui la connettività Internet non venga rilevata, le richieste aggiuntive attenderanno fino a quando non sarà.

Linee guida per il debug

L'arresto di una sessione di debug in Microsoft Visual Studio è paragonabile alla chiusura dell'app; I caricamenti PUT vengono sospesi e i caricamenti POST vengono terminati. Anche durante il debug, l'app deve enumerare e quindi riavviare o annullare eventuali caricamenti persistenti. Ad esempio, è possibile annullare le operazioni di caricamento persistenti enumerate dell'app all'avvio dell'app se non c'è interesse nelle operazioni precedenti per la sessione di debug.

Durante l'enumerazione dei download/caricamenti all'avvio dell'app durante una sessione di debug, è possibile annullarli se non c'è interesse per le operazioni precedenti per la sessione di debug. Si noti che se sono presenti aggiornamenti del progetto di Visual Studio, ad esempio le modifiche al manifesto dell'app e l'app viene disinstallata e ridistribuiti, GetCurrentUploadsAsync non è possibile enumerare le operazioni create usando la distribuzione precedente dell'app.

Quando si usa il trasferimento in background durante lo sviluppo, è possibile che si verifichi una situazione in cui le cache interne delle operazioni di trasferimento attive e completate possano uscire dalla sincronizzazione. Ciò può comportare l'impossibilità di avviare nuove operazioni di trasferimento o interagire con le operazioni esistenti e oggetti BackgroundTransferGroup. In alcuni casi, il tentativo di interagire con le operazioni esistenti può causare un arresto anomalo. Questo risultato può verificarsi se la proprietà TransferBehavior è impostata su Parallel. Questo problema si verifica solo in determinati scenari durante lo sviluppo e non è applicabile agli utenti finali dell'app.

Quattro scenari che usano Visual Studio possono causare questo problema.

  • Si crea un nuovo progetto con lo stesso nome dell'app di un progetto esistente, ma un linguaggio diverso, ad esempio da C++ a C#.
  • Si modifica l'architettura di destinazione (da x86 a x64, ad esempio) in un progetto esistente.
  • Si modificano le impostazioni cultura (da neutrale a en-US, ad esempio) in un progetto esistente.
  • Aggiungere o rimuovere una funzionalità nel manifesto del pacchetto (aggiungendo ad esempio Enterprise Authentication, ad esempio) in un progetto esistente.

La manutenzione regolare delle app, inclusi gli aggiornamenti del manifesto che aggiungono o rimuovono funzionalità, non attivano questo problema nelle distribuzioni degli utenti finali dell'app. Per risolvere questo problema, disinstallare completamente tutte le versioni dell'app e distribuirla nuovamente con il nuovo linguaggio, architettura, impostazioni cultura o funzionalità. Questa operazione può essere eseguita tramite la schermata start o tramite PowerShell e il cmdlet Remove-AppxPackage.

Eccezioni in Windows.Networking.BackgroundTransfer

Viene generata un'eccezione quando viene passata una stringa non valida per un URI (Uniform Resource Identifier) al costruttore per l'oggetto Windows.Foundation.Uri.

.NET: Il tipo di Windows.Foundation.Uri viene visualizzato come System.Uri in C# e VB.

In C# e Visual Basic questo errore può essere evitato usando la classe System.Uri in .NET 4.5 e uno dei metodi System.Uri.TryCreate per testare la stringa ricevuta dall’utente dell’app prima che venga costruito l'URI.

In C++, non esiste alcun metodo per provare e analizzare una stringa in un URI. Se un'app ottiene l'input dall'utente per il Windows.Foundation.Uri, il costruttore deve trovarsi in un blocco try/catch. In questo modo, se viene generata un'eccezione, l'app può inviare una notifica all'utente e richiedere un nuovo nome host.

Lo spazio dei nomi Windows.Networking.backgroundTransfer include metodi helper pratici e usa enumerazioni nello spazio dei nomi Windows.Networking.Sockets per la gestione degli errori. Questo può essere utile per gestire eccezioni di rete specifiche in modo diverso nell'app.

Viene restituito un errore in un metodo asincrono nello spazio dei nomi Windows.Networking.backgroundTransfer come valore HRESULT. Il metodo BackgroundTransferError.GetStatus viene utilizzato per convertire un errore di rete da un'operazione di trasferimento in background a un Valore di enumerazione WebErrorStatus. La maggior parte dei valori di enumerazione WebErrorStatus corrisponde a un errore restituito dall'operazione client HTTP o FTP nativa. L'app può filtrare i valori di enumerazione specifici di WebErrorStatus allo scopo di modificare il comportamento dell'app a seconda della causa dell'eccezione.

Per gli errori di convalida dei parametri, un'app può anche usare HRESULT dall'eccezione per ottenere informazioni più dettagliate sull'errore che ha causato l'eccezione. I possibili valori HRESULT sono elencati nel file di intestazione Winerror.h. Per gran parte degli errori di convalida dei parametri, il valore HRESULT restituito è E\_INVALIDARG.

API importanti