Puis-je créer une barre de progression de téléchargement dans un bloc Iterator?
-
15-11-2019 - |
Question
Je sais que les barres de progrès en elles-mêmes ont déjà été invitées à mort, mais j'ai des problèmes avec un. J'ai besoin de télécharger un fichier via FTP, j'utilise webClient, les données téléchargées doivent être enregistrées dans un tableau d'octets, mais WebClient.DowloadDataasync ne peut pas les retourner directement, donc je dois utiliser la méthode DownloadDatacompleted pour accéder aux données . Tout jusqu'à ce qu'il soit bon, mais le problème est que je ne peux pas "faire une pause" le bloc d'iEnumerator sans bloquer l'ensemble essaie d'y accéder. Lorsque le fichier à télécharger était en http, j'ai utilisé www et je n'ai eu aucun problème, mais il a dû être déplacé vers FTP. Utilisation de WebClient.DownloadData fonctionne, mais on m'a demandé d'inclure une barre de progression. Quoi qu'il en soit, voici le code:
IEnumerator DownloadGame(Dictionary<string, string> settingsDict)
{
statusText = "Starting download...";
WebClient request = new WebClient();
request.Credentials = new NetworkCredential("user", "password");
request.DownloadDataCompleted += DownloadDataCompleted;
//byte[] fileData = request.DownloadData(settingsDict["downloadlink"]); This works, but is no good since it blocks the thread
request.DownloadDataAsync(new Uri(settingsDict["downloadlink"]),"somefilepath");
//do{}while(!downloadFinished); This also works but blocks the thread anyway
//Process the update
string tmpRoot = TMPFolder();
string tmpFolder = tmpRoot + Application.platform + settingsDict["latestVersion"] + "/";
if (!UnzipUpdate(fileData, tmpFolder))//fail here, in this case fileData is global
{
DeleteDirectory(tmpRoot);
yield break;
}
if (!ProcessUpdateData(tmpFolder))
{
DeleteDirectory(tmpRoot);
yield break;
}
DeleteDirectory(tmpRoot);
settingsDict["thisVersion"] = GetNextVersion();
}
void DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e){
fileData = e.Result;
downloadFinished = true;
}
La solution
Vous pouvez utiliser quelque chose comme celui-ci en fonction d'un précédent post Stakoverflow.
Le plus facile est d'utiliser BackgroundWorker
Et mettez votre code dans DoWork
gestionnaire d'événements. Et signaler les progrès avec BackgroundWorker.ReportProgress
.
L'idée de base:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
var ftpWebRequest = (FtpWebRequest)WebRequest.Create("ftp://xxx.com");
ftpWebRequest.Method = WebRequestMethods.Ftp.UploadFile; //or DownLoad
using (var inputStream = File.OpenRead(fileName))
using (var outputStream = ftpWebRequest.GetRequestStream())
{
var buffer = new byte[1024 * 1024];
int totalReadBytesCount = 0;
int readBytesCount;
while ((readBytesCount = inputStream.Read(buffer, 0, buffer.Length)) > 0)
{
outputStream.Write(buffer, 0, readBytesCount);
totalReadBytesCount += readBytesCount;
var progress = totalReadBytesCount * 100.0 / inputStream.Length;
backgroundWorker1.ReportProgress((int)progress);
}
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
}
S'assurer WorkerReportsProgress
est autorisé
backgroundWorker2.WorkerReportsProgress = true;
Avec BackgroundWorker
Vous pouvez également implémenter une annulation de téléchargement.