Frage

Ich habe in meinem Formularkonstruktor nach dem InitializeComponent dem folgenden Code:

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

Wenn ich meine Form starten, wird die Benutzeroberfläche erscheint nicht bis client_DownloadDataCompleted angehoben wird. Die client_DownloadDataCompleted Methode ist leer, so dass es kein Problem gibt.

Was ich falsch mache? Wie soll dies tun, ohne die UI Einfrieren?

Vielen Dank für Ihre Zeit.
Mit freundlichen Grüßen.

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;
    }
}
War es hilfreich?

Lösung

Nun, da wir vollständigen Code haben, kann ich sagen, ich bin auf jeden Fall das Problem nicht zu sehen -. Nicht ganz so beschrieben, jedenfalls

Ich habe ein bisschen Protokollierung bekommt kurz vor, um anzuzeigen, und nach dem DownloadDataAsync ruft, und wenn der fertig Handler ausgelöst wird. Wenn ich eine große Datei über 3G herunterladen, es ist eine Pause zwischen „vorher“ und „nachher“, aber die UI kommt Zeiten vor der Datei abgeschlossen hat herunterzuladen.

Ich habe den Verdacht, dass die connect wird synchron gemacht, aber der eigentliche Download ist asynchron. Das ist immer noch bedauerlich, natürlich - und vielleicht all das in einem anderen Thread Tochern ist der Weg zu gehen -. Aber wenn ich mich richtig es ist zumindest Wissenswertes über

Andere Tipps

das gleiche Problem aufgetreten, und eine Lösung gefunden. Ganz komplexe Diskussion hier: http://social.msdn.microsoft.com/Forums/en-US/a00dba00-5432-450b-9904-9d343c11888d/webclient-downloadstringasync-freeze-my-ui?forum=ncl

Kurz gesagt, ist das Problem, Web-Client für Proxy-Server sucht und die App hängt. Die folgende Lösung hilft:

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

Sie möchten den Download in einem anderen Thread ausführen können, finden Sie unter dieses als Ausgangspunkt.

Ich nehme stark an, dass es mit der Entsorgung des WebClient zu tun ist, während Sie es noch für einen asynchronen Aufruf verwendet wird.

Versuchen Sie die Anweisung using entfernen, und rufen Sie Dispose in einem Event-Handler statt. (Oder einfach nur zum Testen, keine Sorge darüber überhaupt zu entsorgen.

Wenn Sie eine kurze, aber vollständige Programm , die das Problem veranschaulicht, das wäre wirklich praktisch.

Neben der Entsorgung von etwas, das möglicherweise noch von dem Asynchron-Aufruf ausgeführt wird, die von anderen Menschen erwähnt worden ist, würde ich empfehlen, gegen Schwergewichts-Material in einem Formular Konstruktor wie dies zu tun.

Machen Sie es in einem OnLoad überschreiben statt, wo Sie auch in der Lage sein wird, die Designmode Eigenschaft zu überprüfen, die Sie mehrere Ebenen der Hölle mit dem VS-Formulardesigner vermeiden helfen.

UNDELETED:. Wie viele denken über die Verwendung von Block wie ich, ich habe bestätigt, dass es nicht im Zusammenhang

Können Sie die Verwendung von Block entfernen, ich denke, es wartet die webclient Instanz zu entsorgen.

DownloadDataAsync vs. Download in einem nicht-UI thread:

DownloadDataAsync ist schön, weil es eigentlich keinen Faden binden, bis die DownloadDataCompletedEvent Handhabung, nachdem der Antrag gestellt wurde und der Server antwortet.

Ich glaube, Jon Skeet auf dem richtigen Weg ist. - Ich habe gelesen, dass die DNS-Auflösung synchron ausführen muß, bevor die asynchrone HTTP-Anforderung in die Warteschlange gestellt und die DownloadDataAsync Aufruf zurückgegeben

Könnte die DNS-Auflösung langsam sein?

Ich habe gerade getestet, die gleiche Sache in einem WPF-Projekt unter VS2010, .NET 4.

Ich bin eine Datei mit einem Fortschrittsbalken Download Prozentsatz zu zeigen, fertig mit WebClient.DownloadDataCompleted etc.

Und zu meinem Erstaunen, ich finde das gleiche @ Dan erwähnt: Innerhalb des Debugger blockiert es den Faden in einer lustigen Art und Weise. Im Debug, werden meine Fortschritte Meter bei 1% aktualisiert, dann tut nichts für eine Weile, dann plötzlich wieder bei 100% aktualisiert. (Debug.WriteLn Aussagen drucken reibungslos durch uns). Und zwischen diesen beiden Zeiten wird die UI eingefroren.

Aber außerhalb des Debuggers, der Fortschrittsbalken bewegt sich sanft von 0% bis 100%, und die UI nie einfriert. Das ist, was man erwarten würde.

versuchen Sie dies:

client.Proxy = GlobalProxySelection.GetEmptyProxy();

Das sieht ein wenig seltsam für mich.

Versuchen Sie, ein Mitglied ref des WebClient zu halten, so dass Sie im Konstruktor zerstören es nicht, vielleicht ist es blockiert auf der client.Dispose ()

Die Verwendung von () Anweisung versucht Dispose () das WebClient zu nennen, während sie noch heruntergeladen. Die Dispose-Methode wahrscheinlich für den Download wartet, bevor Sie fortfahren zu beenden.

Versuchen Sie nicht mit () Erklärung und entsorgen Sie das WebClient in Ihrem DownloadDataCompleted Ereignisse verwendet wird.

Ich kann Ihren Code gut laufen. Und die Form zeigt und der Download abgeschlossen ist, nachdem das Formular auftauchte.

Ich habe keine gefriert, wie Sie erwähnt.

Ich denke, es hat etwas mit der Umwelt zu tun hat Sie es im Inneren ausgeführt werden.

Welche Version von .NET / Visual Studio sind Sie?

Ich habe den Code versucht, und es funktioniert gut.

Könnten Sie Ihren Main (args []) Methode und den Wert von a und b veröffentlichen, wenn dieser ausgeführt wird:

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

Ich habe versucht, es .NET 3.5 und VS2008 in. Ich bin ratlos, aber ich bin überzeugt, es ist mit dem Setup auf Ihrem Computer zu tun. Nicht der Code. Schauen Sie sich diese Dinge:

  • Überprüfen Sie den Thread-Pool (siehe oben). Ich bekomme ein = 250 b = 1000
  • Deaktivieren Sie alle Drittanbieter-Plugins
  • Laden VS "Clean" (Haben Sie neu gestartet)
  • Schließen Sie so viele Programme / Dienste wie möglich
  • Überprüfen Sie Ihre IE-Konfig. Ich denke, dass Klasse verwendet IE-Code / Einstellungen
  • Firewall? Antivirus?
  • Versuchen Sie es auf einem anderen Computer

Ähm .... Ich bin nur neugierig

Haben Sie Firewalls auf?

jeder Firewalls an alle auf Ihrem Rechner?

Vielleicht Zonealarm?

Nach meiner Erfahrung, es ist eine Art-Blöcke den Faden beim Ausführen des Projektes Debuggen (es innerhalb von Visual Studio ausgeführt wird) und wenn Sie den Server zum ersten Mal zugegriffen wird.

Wenn Sie die kompilierte exe ausgeführt wird, die Blockierung nicht wahrnehmbar ist.

Dieses Problem ist noch nicht abgeschlossen, auch in VS2015. Ich dachte, endlich das aus, es ist nichts falsch mit dem Code Menschen verwenden, das Problem ist tatsächlich, wie schnell Sie Daten zu einem Label-Steuerelement schreiben kann, und das ist, was den Prozess auflegt und bewirkt, dass die Benutzeroberfläche einzufrieren. Versuchen Sie, Ihre Etiketten ersetzen, die Sie mit Textboxen in Ihrem Progress Handler verweisen. Dies löste alle Lags in der Benutzeroberfläche für mich, ich hoffe, dass dies hilft anderen, wie ich Stunden damit verbracht, herauszufinden, warum der Code manchmal und andere nicht funktioniert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top