2008-11-07 76 views
5

我在窗體的構造,在InitializeComponent後,下面的代碼:WebClient.DownloadDataAsync被凍結我的UI

using (WebClient client = new WebClient()) 
{ 
    client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted); 
    client.DownloadDataAsync("http://example.com/version.txt"); 
} 

當我開始我的形式,直到client_DownloadDataCompleted提高用戶界面不會出現。 client_DownloadDataCompleted方法爲空,所以這裏沒有問題。

我在做什麼錯了? 如何在不凍結UI的情況下做到這一點?

謝謝你的時間。
此致敬禮。

全碼:

Program.cs的

using System; 
using System.Windows.Forms; 

namespace Lala 
{ 
    static class Program 
    { 
     /// <summary> 
     /// The main entry point for the application. 
     /// </summary> 
     [STAThread] 
     static void Main() 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      Application.Run(new Form1()); 
     } 
    } 
} 

Form1.cs的

using System; 
using System.Net; 
using System.Windows.Forms; 

namespace Lala 
{ 
    public partial class Form1 : Form 
    { 
     WebClient client = new WebClient(); 

     public Form1() 
     { 
      client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted); 
      client.DownloadDataAsync(new Uri("http://www.google.com")); 
      InitializeComponent(); 
     } 

     void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e) 
     { 
      textBox1.Text += "A"; 
     } 
    } 

    partial class Form1 
    { 
     /// <summary> 
     /// Required designer variable. 
     /// </summary> 
     private System.ComponentModel.IContainer components = null; 

     /// <summary> 
     /// Clean up any resources being used. 
     /// </summary> 
     /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 

     #region Windows Form Designer generated code 

     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     private void InitializeComponent() 
     { 
      this.button1 = new System.Windows.Forms.Button(); 
      this.textBox1 = new System.Windows.Forms.TextBox(); 
      this.SuspendLayout(); 
      // 
      // button1 
      // 
      this.button1.Location = new System.Drawing.Point(12, 12); 
      this.button1.Name = "button1"; 
      this.button1.Size = new System.Drawing.Size(75, 23); 
      this.button1.TabIndex = 0; 
      this.button1.Text = "button1"; 
      this.button1.UseVisualStyleBackColor = true; 
      // 
      // textBox1 
      // 
      this.textBox1.Location = new System.Drawing.Point(12, 41); 
      this.textBox1.Multiline = true; 
      this.textBox1.Name = "textBox1"; 
      this.textBox1.Size = new System.Drawing.Size(468, 213); 
      this.textBox1.TabIndex = 1; 
      // 
      // Form1 
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
      this.ClientSize = new System.Drawing.Size(492, 266); 
      this.Controls.Add(this.textBox1); 
      this.Controls.Add(this.button1); 
      this.Name = "Form1"; 
      this.Text = "Form1"; 
      this.ResumeLayout(false); 
      this.PerformLayout(); 

     } 

     #endregion 

     private System.Windows.Forms.Button button1; 
     private System.Windows.Forms.TextBox textBox1; 
    } 
} 
+0

你的意思是DownloadData或DownloadString? – chakrit 2008-11-07 11:41:49

+0

你是否設法解決這個問題? – 2008-11-12 23:16:23

+0

分辨率爲`client.Proxy = null;`。看到這個答案類似的問題:http://stackoverflow.com/questions/4415443/system-net-webclient-unreasonably-slow/4420429#4420429 – 2011-05-28 00:03:42

回答

4

,我們已經有了完整的代碼,我可以說我肯定沒有看到這個問題 - 並不像描述的,無論如何。

我有位記錄的只是前後DownloadDataAsync來電顯示,當完成處理程序被觸發。如果我通過3G下載大文件,在「之前」和「之後」之間暫停,但是UI在文件完成下載之前出現。

我懷疑連接是同步完成的,但實際下載是異步的。當然,這仍然是不幸的 - 並且可能將所有這些都推到一個不同的線程中 - 但是如果我是對的,至少值得了解。

1

你想運行下載在不同的線程,見this作爲一個起點。

+0

那麼...... Async是什麼? 如果我打算使用BackgroundWorker,爲什麼我應該使用DownloadDataAsync而不是DownloadData? – 2008-11-07 11:12:44

0

我試過你的代碼,它工作正常。

你能張貼您的主(參數[])方法的和b的值,這是運行時:

int a, b; 
    ThreadPool.GetMaxThreads(out a, out b); 

我想它在.net 3.5和VS2008。我很茫然,但我確信這是與你的機器上的設置有關。不是代碼。檢查這些東西:

  • 檢查線程池(上面)。我收到了= 250 B = 1000
  • 禁用所有第三方插件
  • 負載VS「清潔」(你有沒有重新啓動)
  • 關閉許多程序/服務,您可以
  • 檢查你的IE瀏覽器的配置。我覺得那個班使用IE代碼/設置
  • 防火牆?防病毒軟件?
  • 嘗試在另一臺計算機
+0

@Matias:不應該由響應者提供一個完整的程序來演示問題 - 請幫助我們通過使我們容易複製來幫助您。 – 2008-11-07 11:25:34

+0

該代碼不適合我。在下載的字符串之前,我得到了1ms的END END。它需要5秒鐘才能到達「END OF APP」 – 2008-11-07 11:25:43

+0

@Matias我嘗試了您的代碼,並且UI完全響應。發佈你的靜態主要方法/類。 – 2008-11-07 11:34:09

0

這看起來有點怪我的。

儘量保持Web客戶端的成員引用,這樣你就不能在構造破壞它,也許是上阻塞client.Dispose()

+0

不,我得到同樣的問題。 – 2008-11-07 11:19:27

1

取消刪除:由於許多想想使用塊像我那麼,我已經確認它是不是有關。

你可以刪除使用塊,我認爲它正在等待處理webclient實例。

+0

不,沒有使用相同的結果。 – 2008-11-07 11:18:13

1

我強烈懷疑這是爲了處理WebClient,而您仍然在使用它進行異步調用。

嘗試刪除using語句,並在事件處理程序調用Dispose來代替。 (或者只是用於測試,不用擔心處置它。

如果你能發佈short but complete program這表明了問題,這將是非常方便的。

+0

我已經發布了完整的代碼。你現在可以檢查它。 – 2008-11-07 11:30:25

0

的使用()語句正試圖調用雖然它仍然在下載Web客戶端的Dispose()方法。Dispose方法可能等待下載,然後再繼續完成。

儘量不要使用使用()語句,並在您DownloadDataCompleted事件中的Web客戶端的處理。

1

以及處置可能仍在運行的東西ync調用,這是其他人提到的,我強烈建議不要在表單的構造函數中使用像這樣的重量級的東西。

做在一個onload覆蓋代替,在這裏你還可以檢查DesignMode屬性,這將有助於你避免地獄的幾個層次與VS窗體設計器。

0

我可以正常運行你的代碼。表單顯示出來,下載完成後表單出現。

我沒有任何凍結你所說。

我認爲這是與你在裏面運行它的環境。

你在什麼版本的.NET/Visual Studio?

0

嗯....我只是好奇

你有任何防火牆?

任何防火牆在您的機器上?

也許ZoneAlarm?現在

1

DownloadDataAsync與DownloadData在非UI線程:

DownloadDataAsync是好的,因爲它實際上並不佔用一個線程,直到處理DownloadDataCompletedEvent,請求已經被製成,服務器響應後。

我相信喬恩斯基特是在正確的軌道上 - 我讀過的異步HTTP請求是排隊和DownloadDataAsync調用返回之前,DNS解析必須同步完成。

DNS解析速度可能會變慢嗎?

0

在我的經驗,排序塊運行調試項目時,該線程(在Visual Studio中運行它),並訪問服務器的第一次時。

運行編譯的exe文件時,阻塞是不可感知的。

1

我剛剛測試了同樣的事情在VS2010下一個WPF項目,.NET 4

我下載一個文件,一個進度條,顯示比例使用WebClient.DownloadDataCompleted等

完成了

而令我驚訝的是,我發現了@丹提到的同樣的東西: 在調試器中,它以有趣的方式阻塞了線程。在調試中,我的進度計以1%更新,然後暫時不做任何事情,然後突然以100%更新。 (Debug.WriteLn語句平穩打印)。在這兩次之間,用戶界面被凍結。

但是在調試器外部,進度條平滑地移動從0%到100%,並且UI從未凍結。這是你所期望的。

1

試試這個:

client.Proxy = GlobalProxySelection.GetEmptyProxy(); 
0

即使在VS2015中,此問題仍然存在。我終於明白了這一點,人們正在使用的代碼沒有問題,問題實際上您可以將數據寫入標籤控件的速度有多快,並且這會導致進程掛起並導致您的UI凍結。嘗試替換您在progresschanged處理程序中使用文本框引用的標籤。這爲我解決了UI中的所有滯後問題,我希望這可以幫助其他人,因爲我花了數小時試圖弄清楚爲什麼代碼有時會起作用,而不是其他時間。