2008-11-07 81 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中的所有滞后问题,我希望这可以帮助其他人,因为我花了数小时试图弄清楚为什么代码有时会起作用,而不是其他时间。