2012-03-01 4 views
0

Я знаю, что баги прогресса уже просили до смерти, но у меня проблемы с одним. Мне нужно загрузить файл через FTP, я использую WebClient, загруженные данные должны быть сохранены в массив байтов, но WebClient.DownloadDataAsync не может вернуть его напрямую, поэтому я должен использовать метод DownloadDataCompleted для доступа к данным , Все до тех пор, пока не будет нормально, но проблема в том, что я не могу «приостановить» блок IEnumerator, не блокируя весь поток, и если я его не приостанавливаю, приложение выйдет из строя, потому что массив байтов не существует, когда он пытается получить к нему доступ. Когда файл для загрузки был в http, я использовал WWW и не имел проблем, но его нужно было перенести на FTP. Использование WebClient.DownloadData работает, но меня попросили включить индикатор выполнения. Во всяком случае, here's код:Могу ли я создать индикатор выполнения загрузки внутри блока итератора?

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; 
} 

ответ

0

вы можете использовать что-то вроде этого на основе предыдущего поста Stakoverflow ..

Проще всего использовать BackgroundWorker и поместить свой код в DoWork обработчик событий. И сообщите о достигнутом прогрессе с BackgroundWorker.ReportProgress.

Основная идея:

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; 
} 

Убедитесь WorkerReportsProgress включен

backgroundWorker2.WorkerReportsProgress = true; 

С BackgroundWorker вы также можете легко осуществить отмену загрузки.

+0

Threading действительно помог, спасибо. – Samssonart

+0

Добро пожаловать .. счастливая кодировка Marco – MethodMan

Смежные вопросы