Pergunta

Eu tenho no meu construtor do formulário, após o InitializeComponent o código a seguir:

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

Quando eu começar a minha forma, a interface do usuário não aparece até client_DownloadDataCompleted é levantada. O método client_DownloadDataCompleted está vazia, então não há nenhum problema lá.

O que eu estou fazendo errado? Como é suposto fazer isso sem o congelamento da interface do usuário?

Obrigado pelo seu tempo.
Com os melhores cumprimentos.

completo Código:

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;
    }
}
Foi útil?

Solução

Agora que temos código completo, eu posso dizer que eu definitivamente não estou vendo o problema -. Não exatamente como descrito, de qualquer maneira

Eu tenho um pouco de logging para indicar imediatamente antes e após as chamadas DownloadDataAsync, e quando o manipulador concluído é acionado. Se eu baixar um arquivo grande através de 3G, há é uma pausa entre "antes" e "depois", mas o UI vem acima idades antes da conclusão do carregamento de arquivo.

Eu tenho uma suspeita de que o Conectar é feito de forma síncrona, mas o download real é assíncrona. Isso ainda é lamentável, é claro - e, possivelmente, punting tudo isso em um segmento diferente é o caminho a percorrer -. Mas se eu estou certo que é, pelo menos, vale a pena conhecer

Outras dicas

encontrou o mesmo problema, e encontrou uma solução. Bastante complexa discussão aqui: http://social.msdn.microsoft.com/Forums/en-US/a00dba00-5432-450b-9904-9d343c11888d/webclient-downloadstringasync-freeze-my-ui?forum=ncl

Em suma, o problema é o cliente web está à procura de servidores proxy e pendurar o aplicativo. A solução a seguir ajuda:

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

Você deseja executar o download em um segmento diferente, consulte este como um ponto de partida.

Eu suspeito fortemente que ele tem a ver com a eliminação do WebClient enquanto você ainda está usando-o para uma chamada assíncrona.

Tente remover a instrução usando, e chamar Dispose em um manipulador de eventos em seu lugar. (Ou apenas para testes, não se preocupe com a eliminação lo em tudo.

Se você pudesse postar uma curto, mas completo programa que demonstra o problema, que seria realmente útil.

Assim como a eliminação de algo que é, possivelmente, ainda correndo a chamada assíncrona que foi mencionado por outras pessoas, eu recomendo fortemente contra fazer coisas pesado como este no construtor do formulário.

Fazê-lo em uma substituição OnLoad em vez disso, onde você também será capaz de verificar a propriedade DesignMode que irá ajudá-lo a evitar a vários níveis do inferno com o VS Forms Designer.

não excluídos:. como muitos pensam sobre o uso de bloco como eu faço, eu já confirmou que é não relacionadas

Você pode remover o bloco usando, eu acho que está esperando para descartar a instância webclient.

DownloadDataAsync vs. DownloadDataHeader em um segmento não-UI:

DownloadDataAsync é bom porque ele realmente não amarrar um fio até manusear o DownloadDataCompletedEvent, após o pedido foi feito e as responde servidor.

Eu acredito que Jon Skeet é no caminho certo -. Eu li que a resolução de DNS deve concluir síncrona antes da solicitação HTTP assíncrona está na fila e a chamada retorna DownloadDataAsync

Será que a resolução de DNS ser lento?

Eu apenas testada a mesma coisa em um projeto WPF sob VS2010, .NET 4.

Eu estou baixando um arquivo com uma barra de progresso para mostrar porcentagem concluída usando WebClient.DownloadDataCompleted etc.

E, para minha surpresa, eu estou achando a mesma coisa @ Dan mencionado: Dentro dos depurador ele bloqueia o fio de uma forma engraçada. Na depuração, meu medidor de progresso é atualizado em 1%, então não faz nada por um tempo, em seguida, atualiza novamente de repente em 100%. (Declarações Debug.WriteLn imprimir sem problemas em todo). E entre estas duas vezes, a interface do usuário é congelada.

Mas fora do depurador, a barra de progresso se move suavemente de 0% a 100%, e a interface do usuário não congela. Que é o que você esperaria.

tente o seguinte:

client.Proxy = GlobalProxySelection.GetEmptyProxy();

Isso parece um pouco estranho para mim.

Tente manter um ref membro do WebClient para que você não destruí-lo no construtor, talvez ele está bloqueando no client.Dispose ()

A declaração usando () está tentando chamar Dispose () do WebClient enquanto ele ainda está baixando. O método Dispose provavelmente espera que o download terminar antes de continuar.

Tente não usar uma declaração usando () e dispor do WebClient em seu evento DownloadDataCompleted.

Eu posso executar o seu bom código. E a forma aparece e a conclusão da transferência após o formulário apareceu.

Eu não tenho nenhum congela como você mencionou.

Eu acho que tem algo a ver com o ambiente que você está executando-o para dentro.

Qual versão do .NET / Visual Studio você está?

Eu tentei o seu código e ele funciona muito bem.

Você poderia postar o seu método (Args []) principal e o valor de a e b quando este é executado:

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

Eu tentei-o em .NET 3.5 e VS2008. Eu estou em uma perda, mas estou convencido de que tem a ver com a configuração em sua máquina. Não o código. Confira essas coisas:

  • Verifique o pool de threads (acima). Recebo a = 250 b = 1000
  • Desativar todos os plug-ins de terceiros
  • Load VS "Clean" (Você reiniciado)
  • Fechar tantos programas / serviços, como você pode
  • Verifique sua configuração do IE. Eu acho que a classe usa IE / código de configurações
  • Firewall? AntiVirus?
  • Experimente-o em outro computador

Ummm .... Eu sou apenas curioso

Você tem Firewalls on?

qualquer firewalls em tudo em sua máquina?

Talvez ZoneAlarm?

Na minha experiência, espécie de bloqueia o segmento ao executar a depuração do projeto (executá-lo dentro do Visual Studio) e ao acessar o servidor pela primeira vez.

Ao executar o exe compilado, o bloqueio não é perceptível.

Este problema ainda está em curso, mesmo em VS2015. Eu finalmente descobri isso, não há nada de errado com o código de pessoas estão usando, o problema é realmente o quão rápido você pode gravar dados em um controle de rótulo e é isso que desliga o processo e faz com que seu UI para congelar. Tente substituir suas etiquetas que você faz referência com caixas de texto em seus manipuladores de ProgressChanged. Isso resolveu todos os desfasamentos no UI para mim, eu espero que isso ajude os outros como eu passei horas tentando descobrir por que o código funcionou algumas vezes e não outros.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top