2014-10-08 52 views
1

我有以下代碼從FTP服務器下載一些文件: 編輯:我已經使用DotNet,一個很好的FTP WPF庫解決了問題!鼠標結束時的下載速度過低窗口

public partial class MainWindow 
{ 
    DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer(); 
    private byte[] downloadedData; 
    string FTPAddress = "ftp://ftp.cluster007.ovh.net"; 

    double currentBytes; 
    double oldBytes; 


    public MainWindow() 
    { 
     InitializeComponent(); 

     // DispatcherTimer setup 
     dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick); 
     dispatcherTimer.Interval = new TimeSpan(0, 0, 1); 


    } 

    public static void DoEvents() 
    { 
     Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, 
      new Action(delegate { })); 
    } 

    private void dispatcherTimer_Tick(object sender, EventArgs e) 
    { 
     currentBytes = Dl_ProgressBar.Value; 
     Dl_Speed.Content = "Vitesse : " + ((currentBytes - oldBytes)/1000000).ToString("0.00") + " Mo/s"; 

     oldBytes = Dl_ProgressBar.Value; 

     // Forcing the CommandManager to raise the RequerySuggested event 
     CommandManager.InvalidateRequerySuggested(); 
    } 

    private void Dl_Button_Click(object sender, RoutedEventArgs e) 
    { 

     downloadFile(); 
    } 

    private void downloadFile() 
    { 

     downloadedData = new byte[0]; 

     try 
     { 

      //Create FTP request 
      //Note: format is ftp://server.com/file.ext 
      FtpWebRequest request = FtpWebRequest.Create(FTPAddress + "/" + filename) as FtpWebRequest; 

      //Get the file size first (for progress bar) 
      request.Method = WebRequestMethods.Ftp.GetFileSize; 
      request.Credentials = new NetworkCredential(username, password); 
      request.UsePassive = true; 
      request.UseBinary = true; 
      request.KeepAlive = true; //don't close the connection 

      int dataLength = (int)request.GetResponse().ContentLength; 

      Dl_Status.Content = "Téléchargement en cours..."; 
      DoEvents(); 

      //Now get the actual data 
      request = FtpWebRequest.Create(FTPAddress + "/" + filename) as FtpWebRequest; 
      request.Method = WebRequestMethods.Ftp.DownloadFile; 
      request.Credentials = new NetworkCredential(username, password); 
      request.UsePassive = true; 
      request.UseBinary = true; 
      request.KeepAlive = false; //close the connection when done 

      //Set up progress bar 
      Dl_ProgressBar.Value = 0; 
      Dl_ProgressBar.Maximum = dataLength; 

      //Streams 
      FtpWebResponse response = request.GetResponse() as FtpWebResponse; 
      Stream reader = response.GetResponseStream(); 

      //Download to memory 
      //Note: adjust the streams here to download directly to the hard drive 
      MemoryStream memStream = new MemoryStream(); 
      byte[] buffer = new byte[1024]; //downloads in chuncks 
      dispatcherTimer.Start();    
      while (true) 
      { 
       DoEvents(); //prevent application from crashing 
       int bytesRead = reader.Read(buffer, 0, buffer.Length); 

       if (bytesRead == 0) 
       { 
        //Nothing was read, finished downloading 
        Dl_ProgressBar.Value = Dl_ProgressBar.Maximum; 
        Dl_Percent.Content = "Progression : 100%"; 

        DoEvents(); 
        break; 
       } 
       else 
       { 
        //Write the downloaded data 
        memStream.Write(buffer, 0, bytesRead); 

        //Update the progress bar 
        if (Dl_ProgressBar.Value + bytesRead <= Dl_ProgressBar.Maximum) 
        { 
         Dl_ProgressBar.Value += bytesRead; 
         Dl_Percent.Content = "Progression : " + ((Dl_ProgressBar.Value/1000000000000000) * dataLength).ToString("0.00") + "%"; 
         DoEvents(); 
        } 
       } 
      } 

      //Convert the downloaded stream to a byte array 
      downloadedData = memStream.ToArray(); 

      //Clean up 
      reader.Close(); 
      memStream.Close(); 
      response.Close(); 

      Dl_Status.Content = "Téléchargement terminé"; 
      DoEvents(); 
     } 
     catch (Exception) 
     { 
      Dl_Status.Content = "Erreur de connexion au FTP"; 
     } 
    } 

} 

我的問題是,當我通過鼠標懸停在該窗口中,將下載速度顯著下跌... 它從3.70Mb/S變化爲2.20Mb/s的。 當我將鼠標移出窗外時,沒有問題,但是當它結束時,它會變慢,尤其是當我做一些非常短暫的動作時,下載速度會達到0.20Mb/s。 我試過使用線程和調度程序,但它是一樣的。

+0

歡迎來到堆棧溢出!請不要在您的帖子的標題中添加標籤。 – pquest 2014-10-08 16:32:42

+1

我有一種奇怪的感覺,你的'DoEvent()'是你的問題的原因。我建議不要使用主線程來執行下載,而是使用'BackgroundWorker'來查看。 – Vlad 2014-10-08 16:34:27

+0

@Clemens哈,我當然做得很好。 – Vlad 2014-10-08 16:39:28

回答

3

爲了回答您的具體問題,WPF的Dispatcher使用優先級隊列,Input級事件(如那些來自鼠標移動始發)在Background級別的事件優先。您的DoEvents()方法週期性地排除優先級爲Background以上的所有事件的消息隊列,因此當您將鼠標移動到窗口上時,隊列將填充輸入事件進行處理。這意味着DoEvents需要更長的時間才能恢復,並且在恢復處理下載之前需要更多的時間。

這就是說,這是一個可怕的方式來完成下載;你應該從來沒有使用這種DoEvents()黑客在WPF;對C#的asyncawait功能做一些研究(或者,如果這不是一個選項,BackgroundWorker)。您將在StackOverflow上找到很多關於如何進行異步下載的例子,而不必訴諸於這種詭計來保持UI的響應。

+1

我明白,非常感謝! – 2014-10-08 16:39:21