Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
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 e persistono oltre la terminazione dell'app. L'API monitora lo stato della rete e sospende e riprende automaticamente i trasferimenti quando la connettività viene persa e i trasferimenti sono anche con riconoscimento del senso dati e del senso della batteria, 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). FTP è supportato anche, ma solo per i download.
Note
Le Windows.Networking.BackgroundTransfer API sono API Windows Runtime (WinRT) che funzionano nelle app desktop WinUI 3 (SDK per app di Windows) e nelle app UWP. I trasferimenti in background richiedono l'identità del pacchetto; le app non in pacchetto non possono usare questa API.
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 le API HttpClient anziché il 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 gli oggetti classe BackgroundDownloader o BackgroundUploader . Ogni operazione di trasferimento viene gestita singolarmente dal sistema e separata dall'app chiamante. Le informazioni sullo stato di avanzamento sono disponibili se vuoi assegnare lo stato all'utente nell'interfaccia utente dell'app e la tua 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.
Note
A causa dei vincoli di risorse per app, un'app non deve avere più di 200 trasferimenti (DownloadOperations + UploadOperations) in un determinato momento. Il superamento di tale limite può lasciare la coda di trasferimento dell'app in uno stato irreversibile.
Quando un'applicazione viene avviata, deve chiamare AttachAsync su tutti gli oggetti DownloadOperation e UploadOperation esistenti. Se non si esegue questa operazione, si causerà una perdita di risorse associata ai trasferimenti già completati e, alla lunga, l'uso della funzionalità di trasferimento in background risulterà inutile.
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 del piano dati del vettore e della connettività 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 ai costi, 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 ulteriori informazioni, vedere Utilizzo delle informazioni disponibili sulla connessione di rete.
Nota Per le app in esecuzione nei 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 BackgroundTransferCostPolicy indica che il trasferimento deve continuare.
La tabella seguente indica quando i trasferimenti in background sono consentiti nel telefono per ogni valore BackgroundTransferCostPolicy , dato lo stato corrente del telefono. È possibile usare la classe ConnectionCost per determinare lo stato corrente del telefono.
| Stato del dispositivo | Solo senza restrizioni | Predefinito | Sempre |
|---|---|---|---|
| Connesso al Wi‑Fi | Consenti | Consenti | Consenti |
| Connessione a consumo, non in roaming, sotto il limite di dati, in linea per restare sotto il limite | Deny | Consenti | Consenti |
| Connessione a consumo, non in roaming, entro il limite di dati, si prevede di superare il limite | Deny | Deny | Consenti |
| Connessione a consumo, roaming, entro il limite dati | Deny | Deny | 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. | Deny | Deny | Deny |
Caricamento di file
Quando si usa trasferimento in background, esiste un caricamento come UploadOperation che espone una serie di metodi di controllo usati per riavviare o annullare l'operazione. Gli eventi dell'app (ad esempio, la sospensione o la terminazione) e le modifiche alla connettività vengono gestite automaticamente dal sistema per UploadOperation; i caricamenti continueranno durante i periodi di sospensione dell'app o sospendono e persistono oltre la terminazione 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.
Caricamento di 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 l'oggetto UploadOperation risultante. Nell'esempio seguente viene illustrato come eseguire questa operazione con gli oggetti Uri e StorageFile necessari.
Identificare il file e la destinazione per il caricamento
Prima di iniziare la creazione di un UploadOperation, dobbiamo innanzitutto identificare l'URI della posizione in cui caricare e il file da caricare. Nell'esempio seguente il valore uriString viene popolato usando una stringa dall'input dell'interfaccia utente e il valore del 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 richiesto.
Successivamente, le proprietà dell'oggetto StorageFile (file) fornito 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 UploadOperation (caricamento).
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 notino le chiamate di metodo asincrone definite usando le promise JavaScript. Esaminare una riga dell'ultimo esempio:
promise = upload.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 con 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 avviee in genere 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 l'oggetto UploadOperation risultante.
Prima di tutto, la stringa URI fornita dall'utente viene inizializzata come URI. Successivamente, la matrice di oggetti IStorageFile (file) passati a questo metodo viene iterata attraverso, 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'operazione 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.
Prima di definire la funzione che enumera le operazioni persistenti, è necessario creare una matrice che conterrà gli oggetti UploadOperation che restituirà:
var uploadOperations = [];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 a UploadOperation, se persistente 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); } } };
Scaricamento dei 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, sospensione o terminazione) e le modifiche alla connettività vengono gestite automaticamente dal sistema per DownloadOperation; I download continueranno durante i periodi di sospensione dell'app o sospendono e persistono oltre la terminazione 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 le API HttpClient anziché il trasferimento in background.
Gli esempi seguenti illustrano la creazione e l'inizializzazione di un download di base e illustrano 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 storageFile che conterrà il file richiesto. In questo esempio il nuovo file viene inserito automaticamente in un percorso predefinito. In alternativa, è possibile usare FileSavePicker per consentire agli utenti di indicare dove salvare il file nel dispositivo. Si noti che il metodo load chiamato per assegnare nuovamente i callback a DownloadOperation, se persistente tramite terminazione dell'app, si trova nella classe DownloadOp 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 notino le chiamate di metodi asincroni definite mediante promise 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 con promesse.
Aggiunta di ulteriori metodi di controllo delle operazioni
Il livello di controllo può essere aumentato implementando metodi DownloadOperation aggiuntivi. 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 oggetto 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 mantenuti in background. Gli esempi seguenti illustrano come introdurre nuovamente i download salvati in modo permanente in una nuova sessione dell'app.
Prima di definire la funzione che enumera le operazioni persistenti, è necessario creare una matrice che conterrà gli oggetti DownloadOperation che restituirà:
var downloadOps = [];Successivamente si definisce la funzione che enumera le operazioni persistenti e le archivia nella matrice. Si noti che il metodo load chiamato per assegnare nuovamente i callback per un oggetto DownloadOperation persistente 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); } });È ora possibile usare l'elenco popolato per riavviare le operazioni in sospeso.
Post-elaborazione
Una nuova funzionalità in Windows 10 è la possibilità di eseguire il codice dell'applicazione al completamento 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. Crei un'attività in background e la associ ai trasferimenti prima di avviare i trasferimenti. I trasferimenti vengono quindi eseguiti in background e, quando sono completati, viene richiamata l'attività in background per eseguire la post-elaborazione.
La post-elaborazione usa una nuova classe BackgroundTransferCompletionGroup. Questa classe è simile all'oggetto 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.
- Creare un oggetto BackgroundTransferCompletionGroup . Creare quindi un oggetto BackgroundTaskBuilder . Impostare la proprietà Trigger dell'oggetto builder sull'oggetto del gruppo di completamento e la proprietà TaskEntryPoint del builder sul punto di ingresso dell'attività in background da eseguire al completamento 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 si può avere un solo gruppo di completamento per ciascuna registrazione di 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();
- Quindi si associano i trasferimenti in background al gruppo di completamento. Dopo aver creato tutti i trasferimenti, attivare 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();
- 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 che il gestore di completamento in background. L'ordine in cui vengono chiamate le attività in primo piano e in secondo piano non è garantito. Se si definiscono entrambi, è necessario assicurarsi che le due attività funzionino correttamente e non interferiscano tra loro se vengono eseguite contemporaneamente.
Timeout delle richieste
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.
Nota In entrambi gli scenari, supponendo che ci sia connettività Internet, trasferimento in background ritenta una richiesta fino a tre volte automaticamente. Nel caso in cui la connettività Internet non venga rilevata, le richieste aggiuntive resteranno in attesa finché non verrà rilevata.
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, puoi 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 e dei caricamenti all'avvio dell'app, nel corso di una sessione di debug, puoi fare in modo che l'app li annulli se le operazioni precedenti di quella sessione di debug non sono di interesse. Si noti che, se sono presenti aggiornamenti del progetto di Visual Studio, ad esempio modifiche al manifest dell'app, e l'app viene disinstallata e ridistribuita, GetCurrentUploadsAsync non può enumerare le operazioni create usando la precedente distribuzione 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 gli oggetti BackgroundTransferGroup . In alcuni casi, quando si tenta di interagire con operazioni esistenti, potrebbe verificarsi 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 (ad esempio aggiungendo l'autenticazione enterprise) 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 usando 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 il Windows. Oggetto Foundation.Uri.
.NET: Il tipo 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 nella .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. 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 pratici metodi di supporto 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.
Un errore che si verifica in un metodo asincrono nello spazio dei nomi Windows.Networking.backgroundTransfer viene restituito sotto forma di 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. Un'app può filtrare in base a valori di enumerazione WebErrorStatus specifici per 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 la maggior parte degli errori di convalida dei parametri, il valore HRESULT restituito è E_INVALIDARG.