2009-10-09 5 views
0

J'utilise VSTS 2008 + C# .Net + 3.5 + ASP.Net + IIS 7.0 pour développer une application Windows Forms à côté client pour télécharger un fichier, et à côté du serveur, je reçois ce fichier en utilisant un fichier ASPX.pourquoi le code de mon fichier de téléchargement WebClient se bloque?

Je trouve mon application côté client se bloque après cliquez sur le bouton pour déclencher l'événement de téléchargement. Des idées ce qui ne va pas et comment résoudre? Merci!

code côté client,

public partial class Form1 : Form 
    { 
     private static WebClient client = new WebClient(); 
     private static ManualResetEvent uploadLock = new ManualResetEvent(false); 

     private static void Upload() 
     { 
      try 
      { 
       Uri uri = new Uri("http://localhost/Default2.aspx"); 
       String filename = @"C:\Test\1.dat"; 

       client.Headers.Add("UserAgent", "TestAgent"); 
       client.UploadProgressChanged += new UploadProgressChangedEventHandler(UploadProgressCallback); 
       client.UploadFileCompleted += new UploadFileCompletedEventHandler(UploadFileCompleteCallback); 
       client.UploadFileAsync(uri, "POST", filename); 
       uploadLock.WaitOne(); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.StackTrace.ToString()); 
      } 
     } 

     public static void UploadFileCompleteCallback(object sender, UploadFileCompletedEventArgs e) 
     { 
      Console.WriteLine("Completed! "); 
      uploadLock.Set(); 
     } 

     private static void UploadProgressCallback(object sender, UploadProgressChangedEventArgs e) 
     { 
      Console.WriteLine("{0} uploaded {1} of {2} bytes. {3} % complete...", 
       (string)e.UserState, 
       e.BytesSent, 
       e.TotalBytesToSend, 
       e.ProgressPercentage); 

      // Console.WriteLine (e.ProgressPercentage); 
     } 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      Upload(); 
     } 
    } 

code côté serveur:

protected void Page_Load(object sender, EventArgs e) 
    { 
     string agent = HttpContext.Current.Request.Headers["UserAgent"]; 
     using (FileStream file = new FileStream(@"C:\Test\Agent.txt", FileMode.Append, FileAccess.Write)) 
     { 
      byte[] buf = Encoding.UTF8.GetBytes(agent); 
      file.Write(buf, 0, buf.Length); 
     } 

     foreach (string f in Request.Files.AllKeys) 
     { 
      HttpPostedFile file = Request.Files[f]; 
      file.SaveAs("C:\\Test\\UploadFile.dat"); 
     } 
    } 

Répondre

3

vous attendez dans le thread principal des événements Windows, de sorte que votre interface graphique sera gelé.

Essayez ceci (en utilisant des méthodes non statiques vous permet d'utiliser la méthode Control.Invoke pour exécuter callbacks sur les fenêtres fil de l'interface graphique et sans ce fil afin de redessiner)

public partial class Form1 : Form 
{ 
    private static WebClient client = new WebClient(); 
    private static ManualResetEvent uploadLock = new ManualResetEvent(false); 

    private void Upload() 
    { 
     try 
     { 
      Cursor=Cursors.Wait; 
      Uri uri = new Uri("http://localhost/Default2.aspx"); 
      String filename = @"C:\Test\1.dat"; 

      client.Headers.Add("UserAgent", "TestAgent"); 
      client.UploadProgressChanged += new UploadProgressChangedEventHandler(UploadProgressCallback); 
      client.UploadFileCompleted += new UploadFileCompletedEventHandler(UploadFileCompleteCallback); 
      client.UploadFileAsync(uri, "POST", filename);  
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.StackTrace.ToString()); 
      this.Cursor=Cursors.Default; 
      this.Enabled=false; 
     } 
    } 

    public void UploadFileCompleteCallback(object sender, UploadFileCompletedEventArgs e) 
    { 
     // this callback will be invoked by the async upload handler on a ThreadPool thread, so we cannot touch anything GUI-related. For this we have to switch to the GUI thread using control.BeginInvoke 
     if(this.InvokeRequired) 
     { 
      // so this is called in the main GUI thread 
      this.BeginInvoke(new UploadFileCompletedEventHandler(UploadFileCompleteCallback); // beginInvoke frees up the threadpool thread faster. Invoke would wait for completion of the callback before returning. 
     } 
     else 
     { 
      Cursor=Cursors.Default; 
      this.enabled=true; 
      MessageBox.Show(this,"Upload done","Done"); 
     } 
public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      Upload(); 
     } 
    } 
} 

Et faire la même chose votre progression (vous pourriez mettre à jour un indicateur de progression par exemple).

Cheers, Florian

+0

Pourquoi attendre dans le thread principal des événements Windows fera l'interface graphique sera gelé? Avez-vous plus de documents connexes sur ce sujet à recommander de lire? – George2

+1

L'interface graphique de Windows est basée sur les messages, bien que WinForms la cache. Chaque application Windows utilise un « message de pompage » thread qui livrera des messages aux widgets GUI (tels que la souris déplacé, cliquez sur l'utilisateur, touche enfoncée et autres0 beaucoup. exécution des gestionnaires dans la fenêtre principale fil de message, donc si vous êtes en attente d'un événement, vous permet de bloquer les fenêtres pompe de message et l'IUG apparaît « gelé » vous pouvez habituellement dire quand il ne peut pas se redessiner par exemple Voir ici pour une grande ressource:.. http: // msdn. microsoft.com/en-us/library/3s8xdz5c%28VS.80%29.aspx –

+0

Où vous invoquez méthode de chargement? – George2