Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebClient.DownloadDataAsync is freezing my UI

Tags:

c#

.net

webclient

I have in my Form constructor, after the InitializeComponent the following code:

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

When I start my form, the UI doesn't appears till client_DownloadDataCompleted is raised. The client_DownloadDataCompleted method is empty, so there's no problem there.

What I'm doing wrong? How is supposed to do this without freezing the UI?

Thanks for your time.
Best regards.

FULL CODE:

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;
    }
}
like image 848
Tute Avatar asked Nov 07 '08 11:11

Tute


2 Answers

Now that we've got full code, I can say I'm definitely not seeing the problem - not quite as described, anyway.

I've got a bit of logging to indicate just before and after the DownloadDataAsync calls, and when the completed handler is fired. If I download a large file over 3G, there is a pause between "before" and "after" but the UI comes up ages before the file completes downloading.

I have a suspicion that the connect is done synchronously, but the actual download is asynchronous. That's still unfortunate, of course - and possibly punting all of that into a different thread is the way to go - but if I'm right it's at least worth knowing about.

like image 147
Jon Skeet Avatar answered Oct 23 '22 03:10

Jon Skeet


Encountered the same problem, and found a solution. Quite complex discussion here: http://social.msdn.microsoft.com/Forums/en-US/a00dba00-5432-450b-9904-9d343c11888d/webclient-downloadstringasync-freeze-my-ui?forum=ncl

In short, the problem is web client is searching for proxy servers and hanging the app. The following solution helps:

WebClient webClient = new WebClient();
webClient.Proxy = null;
... Do whatever else ...
like image 35
Wiseman Avatar answered Oct 23 '22 04:10

Wiseman