2010-11-23 5 views
1

Supposons que j'ai une classe HttpHelper qui a une GetResponseStream(), que les données de demande de téléchargement montrant les progrès par les événements StatusChanged & ProgressChanged.besoin de conseils sur la façon de faire fonction Async/Non Blocage

public MemoryStream GetResponseStream() { 
    ... 
    Status = Statuses.Uploading; // this doesn't raise StatusChanged 
    // write to request stream 
    ... // as I write to stream, ProgressChanged doesn't get raised too 
    Status = Statuses.Downloading; // this too 
    // write to response stream 
    ... // same here 
    Status = Statuses.Idle; // this runs ok. Event triggered, UI updated 
} 

code @pastebin. GetRequestStream() en ligne 76. La classe elle-même fonctionne très bien, sauf la nécessité de classe à l'aide de l'appeler comme ci-dessous

HttpHelper helper = new HttpHelper("http://localhost/uploadTest.php"); 
helper.AddFileHeader("test.txt", "test.txt", "text/plain", File.ReadAllBytes("./test.txt")); 
helper.StatusChanged += (s, evt) => 
{ 
    _dispatcher.Invoke(new Action(() => txtStatus.Text = helper.Status.ToString())); 

    if (helper.Status == HttpHelper.Statuses.Idle || helper.Status == HttpHelper.Statuses.Error) 
     _dispatcher.Invoke(new Action(() => progBar.IsIndeterminate = false)); 

    if (helper.Status == HttpHelper.Statuses.Error) 
     _dispatcher.Invoke(new Action(() => txtStatus.Text = helper.Error.Message)); 
}; 
helper.ProgressChanged += (s, evt) => 
{ 
    if (helper.Progress.HasValue) 
     _dispatcher.Invoke(new Action(() => progBar.Value = (double)helper.Progress)); 
    else 
     _dispatcher.Invoke(new Action(() => progBar.IsIndeterminate = true)); 
}; 
Task.Factory.StartNew(() => helper.GetResponseString()); 

Si je l'avais appelé la classe en utilisant

helper.GetResponseString(); 

Ensuite, la classe elle-même fonctionnera, mais les événements ne semble pas être élevé. Je pense que cela a à voir avec le thread de l'interface utilisateur bloqué. Comment puis-je recoder la classe de sorte qu'il est plus facile pour la classe utilisatrice de l'utiliser, sans tous les trucs _dispatcher & Task.

En outre, je voudrais savoir avec certitude ce qui provoque les événements/UI à ne pas mettre à jour. Même si le code est synchrone, ne peut-il pas exécuter la propriété changed/events de toute façon, c'est après la lecture/écriture afterall?

+0

Vous devez définir la coloration syntaxique PasteBin sur C#. http://pastebin.com/FeAPB6rU – SLaks

+0

@SLaks, Merci de m'avoir notifié à ce sujet, je devais avoir fait PHP Yest et j'ai oublié de changer la langue –

Répondre

2

Vous devriez envisager d'utiliser le BackgroundWorker au lieu de le faire vous-même à la main. Utilisez ReportProgress pour passer l'état de traitement à votre thread d'interface utilisateur.

+1

Bien que ce soit probablement une bonne suggestion pour cette question, je voudrais ajouter une mise en garde, car il existe des scénarios dans lesquels cela pourrait être moins bon: un problème avec cette suggestion est qu'il finira par consommer un thread aussi longtemps que le travail est en cours. Il est peu probable que ce soit un problème dans le code côté client (ce qui semble être la question), mais sur le code côté serveur, il serait inutile de faire les choses de manière asynchrone. L'utilisation asynchrone complète des classes de mise en réseau permet une utilisation beaucoup plus frugale des threads, ce qui peut parfois améliorer l'évolutivité du serveur. (Mais serait surengineering ici.) –

+0

+1 pour le commentaire Ian. –

Questions connexes