C# : Blocage d'un appel de fonction jusqu'à ce que condition
Je suis en train d'élaborer un C#, Winforms application, une partie de l'application sera en téléchargeant des fichiers sur un serveur web à l'aide de AsyncUpload (à l'aide,en raison de la nécessité d'utiliser un porgress de rappel) , Dans le programme C#
j'ai eu une simple boucle for qui appelle La fonction de Téléchargement
for(int i=0;i < 10 ; i++)
{
Uploadfun();
}
Et pour le fun un peu de magie:
Uploadfun()
{
//Logic comes here
//webClient.UploadFileAsync runs a 2nd thread to perform upload ..
webClient.UploadFileAsync(uri, "PUT", fileNameOnHD);
}
Et une fonction de callback qui est appelée lorsque l'Async téléchargement est terminé
Upload_Completed_callback()
{
//Callback event
}
Modifier
La logique de la séquence:
- Plaisir est appelée (à partir de la boucle)
- Amusant logique est exécuté et terminé..
- Remonte à boucle
- Callback sera appelé par la suite, quand UploadFileAsync (qui est en cours d'exécution un peu de logique dans un autre thread) sera la fin de la
Le problème est sur le 3ème point, lorsque l'exécution se déplace vers l'arrière de la boucle for, j'ai besoin de bloquer la boucle continue jusqu'à ce que la fonction de rappel appelée.
fun
mise en œuvre? Vous devriez probablement envisager de fournir une interface synchrone sur lequel l'API asynchrone est mis en œuvre.La façon dont vous décrivez, votre code semble séquentielle et mono-thread, ce qui signifie que jusqu'à ce que le
callback
fonction est appelée la boucle ne pourra pas continuer. S'il vous plaît corrigez-moi si je me trompe en donnant des explications plus détaillées.Vous faites cela en arrière. Vous devez utiliser la version synchrone de
UploadFile
au cœur de la logique et de l'utilisation d'une API asynchrone sur le dessus de celui-ci si vous en avez besoin.je suis forcé d'utiliser la version Asynchrone, parce que cela me donne le "progrès", les rappels, ce qui est une exigence.
(F# asyncs FTW!)
OriginalL'auteur Madi D. | 2010-02-06
Vous devez vous connecter pour publier un commentaire.
Donc, si je comprends bien, vous voulez appeler
UploadFileAsync
bloquer jusqu'à ce que l'appel asynchrone a frappé votre rappel. Si oui, j'aimerais utiliserAutoResetEvent
je.eÀ l'aide de
AutoResetEvent
signifie que l'état est automatiquement réinitialisé aprèsSet
a été appelé et un thread en attente reçoit le signal par l'intermédiaireWaitOne
okie.. j'ai résolu le problème de l'arrêt,appelé fun() dans un thread séparé, "manifestement" en l'appelant dans le thread principal est à l'origine du problème !, @Juliette un Peu a contribué à faire ressortir le problème.. merci à vous deux =)
OriginalL'auteur zebrabox
En C# les méthodes de bloquer par défaut, de sorte que vous ne devriez pas besoin de faire quoi que ce soit. Je suis en supposant que, pour quelque raison que vous appelez une méthode non bloquante qui démarre une tâche d'arrière-plan /thread /whatever et vous donne un rappel quand il est fait. Vous voulez appeler cela asynchonous méthode d'une manière synchrone.
Vous pouvez appeler
fun
de l'intérieur de la fonction de rappel. Quelque chose le long de ces lignes (pseudo-code):Ceci est similaire à continuation passing style.
Un avantage de cette méthode est que vous pouvez également faire votre méthode asynchrone, sans addition d'autres threads, serrures, ou de la logique supplémentaire - vous juste fournir une fonction de rappel qui votre client peut s'abonner. Il fonctionne bien dans une manifestation axée sur l'environnement.
j'ai besoin de la version asynchrone, car il fournit un "progrès" de callback qui est une exigence fondamentale.
D: Si la condition est que le téléchargement doit se comporter de manière asynchrone, pourquoi ne pas faire votre fonction une fonction async trop, avec un rappel? Pouvez-vous expliquer plus en détail ce que vous êtes en utilisant ce? Est-ce une application WinForms, ASP.NET, etc?
j'ai édité la question et a ajouté des réponses à vos questions, en plus de quelques informations supplémentaires.
+1 pour m'apprendre un nouveau concept, et de me donner une solution alternative!
OriginalL'auteur Mark Byers
Zebrabox ne l'avez droit à l'aide d'un WaitHandle.
Tandis que Juliette solution fonctionne, le thread d'exécution de la spin-attendre consomment une grande quantité de processeur en proportion de la WaitHandle, qui serait essentiellement inactif.
Il ne mange pas beaucoup le processeur, mais il peut empêcher le système de mettre le CPU dans un profond état de repos et donc de tirer vers le bas plus rapidement la batterie d'un ordinateur portable.
OriginalL'auteur Grant Back
Le problème est ici:
Ce que vous faites est séquentielle. Et si vous ne pouvez pas se permettre de bloquer le thread de l'INTERFACE utilisateur, déplacer la boucle fermé le thread d'INTERFACE utilisateur:
Maintenant, vous pouvez bloquer l'exécution de la boucle sans arrêt de votre thread de l'INTERFACE utilisateur, et vous obtenez également l'avantage d'indicateurs de progrès de la classe webclient.
J'apprécie vos commentaires, mais je pense qu'ils sont trompeurs. Tout d'abord, le compilateur ne va pas à optimiser le booléen à l'écart aussi longtemps que son utilisé ou remis quelque part (et c'est sans doute). Deuxièmement, spin-en attente sur un bool et resetEvents sont valables façons de bloquer un thread, les deux sont de la "bonne façon de le faire", ni "mauvais", le choix de l'un ou de l'autre dépend des goûts de le programmeur.
Merci beaucoup pour la vraiment utile de répondre,endded jusqu'en combinant l'enfilage de votre solution avec @zebrabox de resetEvent solution, et maintenant, c'est de travailler.. =)
Selon les règles de l' .NET modèle de mémoire, ces deux sont exactement équivalentes: while(!downloadComplete) { Thread.Sleep(1); } if (!downloadComplete) { while (true) { Thread.Sleep(1); } } Depuis la boucle ne change pas la variable, le compilateur peut déplacer le test en dehors de la boucle. Je vois que vous avez ajouté une erreur de syntaxe en essayant de faire downloadComplete volatile. Si vous corrigez la déclaration, il va empêcher le compilateur de faire de l'optimisation je l'ai mentionné, mais il est encore d'interrogation qui est pire que le cas pour un certain nombre de raisons.
Je vous remercie de votre commentaire, mais
while(!downloadComplete) { Thread.Sleep(1); }
etif (!downloadComplete) { while (true) { Thread.Sleep(1); } }
sont pas l'équivalent, dans tout modèle de mémoire. Auriez-vous l'esprit de la fourniture de certains documentation MSDN ou un exemple de code montrant comment interrogation compile dans le code que vous avez fourni (avec ou sans volatils)?OriginalL'auteur Juliet