2008-11-07 7 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 пуст, поэтому проблем нет.

Что я делаю неправильно? Как это сделать, не замораживая пользовательский интерфейс?

Спасибо за ваше время.
С уважением.

ПОЛНЫЙ КОД:

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, там - пауза между «до» и «после», но пользовательский интерфейс достигает возраста до того, как файл завершит загрузку.

У меня есть подозрение, что подключиться выполняется синхронно, но фактическая загрузка является асинхронной. Это, конечно, все-таки неудачно, и, возможно, все это отразится на другой теме - это путь, но если я прав, это, по крайней мере, стоит знать.

1

Вы хотите запустить загрузку в другом потоке, см this в качестве отправной точки.

+0

Итак ... для чего нужна Async? Если я собираюсь использовать BackgroundWorker, почему я должен использовать DownloadDataAsync вместо DownloadData? – 2008-11-07 11:12:44

0

Я пробовал ваш код, и он отлично работает.

Не могли бы вы опубликовать свой основной метод (Args []) и значения а и Ь, когда это выполняется:

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

Я попробовал это в .NET 3.5 и VS2008. Я в недоумении, но я убежден, что это связано с настройкой на вашем компьютере. Не код. Проверьте эти вещи:

  • Проверьте пул потоков (вверху). Я получаю = 250 б = 1000
  • Отключить все плагины сторонних
  • нагрузки VS «Clean» (перезагружается Вы)
  • Закрыть как многие программы/услуги, как вы можете
  • Проверьте ваш IE конфигурации. Я думаю, что класс использует IE-код/​​настройки
  • Брандмауэр? AntiVirus?
  • Попробуйте на другом компьютере
+0

@Matias: не должно быть ответчиков, чтобы предоставить полную программу, демонстрирующую проблему - пожалуйста, помогите нам помочь вам, облегчив нам воспроизведение. – 2008-11-07 11:25:34

+0

Этот код не работает для меня. Я получаю END OF APP 1ms до загруженной строки. Это займет 5 секунд, чтобы добраться до «END OF APP» – 2008-11-07 11:25:43

+0

@Matias Я пробовал ваш код, и пользовательский интерфейс полностью отвечает требованиям. Отправьте свой статический основной метод/класс. – 2008-11-07 11:34:09

0

Это выглядит немного странно для меня.

Попытайтесь держать член реф в WebClient, чтобы не уничтожить его в конструкторе, может быть, он блокирует на client.Dispose()

+0

Нет, я получаю та же проблема. – 2008-11-07 11:19:27

1

Восстановлено: как многие думают о использовании блока, как я do, я подтвердил, что это не.

Можете ли вы удалить блок использования, я думаю, он ждет, чтобы удалить экземпляр webclient.

+0

Нет, такой же результат без использования. – 2008-11-07 11:18:13

1

Я сильно подозреваю, что это связано с удалением WebClient, пока вы все еще используете его для асинхронного вызова.

Попробуйте удалить оператор using и вызовите Dispose в обработчике событий. (Или просто для тестирования, не беспокойтесь об утилизации вообще.

Если бы вы могли опубликовать short but complete program, который демонстрирует проблему, что было бы очень удобно.

+0

Я опубликовал полный код. Вы можете проверить это сейчас. – 2008-11-07 11:30:25

0

с помощью() оператор пытается позвонить Dispose() на WebClient, пока еще скачиваете. метод Dispose, вероятно, ждет до окончания загрузки, прежде чем продолжить.

Старайтесь не используя, используя утверждение() и распоряжаться WebClient в вашем случае DownloadDataCompleted.

1

Как и удаление того, что, возможно, все еще работает как ync call, о котором говорили другие люди, я бы настоятельно рекомендовал против создания такого тяжелого материала в конструкторе формы.

Сделайте это вместо переопределения OnLoad, где вы также сможете проверить свойство DesignMode, которое поможет вам избежать нескольких уровней ада с помощью конструктора VS-форм.

0

Я могу запустить ваш код в порядке. И появляется форма, и загрузка завершена ПОСЛЕ появления формы.

У меня нет заморозков, как вы упомянули.

Я думаю, что это как-то связано с окружающей средой, в которой вы ее используете.

В какой версии .NET/Visual Studio вы работаете?

0

Мммм .... Я просто любопытно

Есть ли у вас какие-либо брандмауэров?

любой брандмауэры на вашем компьютере?

Возможно, ZoneAlarm?

1

DownloadDataAsync против DownloadData в потоке без пользовательского интерфейса:

DownloadDataAsync хорошо, потому что она на самом деле не подвязать нить до обработки DownloadDataCompletedEvent, после того, как был сделан запрос, а сервер отвечает.

Я считаю, что Джон Скит находится на правильном пути - я прочитал, что разрешение DNS должно выполняться синхронно до того, как асинхронный HTTP-запрос будет поставлен в очередь, и вызов DownloadDataAsync вернется.

Может ли разрешение DNS быть медленным?

0

По моему опыту, он сортирует поток при выполнении отладки проекта (запускает его внутри Visual Studio) и при первом доступе к серверу.

При запуске скомпилированного exe блокировка не воспринимается.

1

Я просто проверял то же самое в проекте WPF под VS2010, .NET 4.

Я загружаю файл с индикатором прогресса, чтобы показать процент завершенного с использованием WebClient.DownloadDataCompleted и т.д.

И, к моему удивлению, я нахожу то же самое @Dan: Внутри отладчика он блокирует поток забавным способом. При отладке мой индикатор прогресса обновляется на 1%, затем ничего не делает, а затем снова обновляется на 100%. (Операторы Debug.WriteLn печатаются плавно). И между этими двумя временами пользовательский интерфейс заморожен.

Но вне отладчика индикатор выполнения перемещается плавно от 0% до 100%, и пользовательский интерфейс никогда не замерзает. Это то, что вы ожидаете.

1

попробовать это:

client.Proxy = GlobalProxySelection.GetEmptyProxy(); 
4

Столкнулся с такой же проблемой и нашел решение. Весьма сложная дискуссия здесь: http://social.msdn.microsoft.com/Forums/en-US/a00dba00-5432-450b-9904-9d343c11888d/webclient-downloadstringasync-freeze-my-ui?forum=ncl

Короче говоря, проблема заключается в том, что веб-клиент ищет прокси-серверы и висит приложение. следующее решение помогает:

WebClient webClient = new WebClient(); 
webClient.Proxy = null; 
... Do whatever else ... 
0

Эта проблема все еще продолжается даже в VS2015. Я, наконец, понял это, нет ничего плохого в том, что люди используют код, проблема в том, насколько быстро вы можете записывать данные в элемент управления меткой, и это то, что зависает от процесса и заставляет ваш пользовательский интерфейс замерзать. Попробуйте заменить ярлыки, с которыми вы ссылаетесь, с текстовыми полями в обработчиках progresschanged. Это решило все задержки в пользовательском интерфейсе для меня, я надеюсь, что это помогает другим, поскольку я потратил часы, пытаясь понять, почему код работал иногда, а не другие.

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