J'ai entendu quelque part que l'attente asynchrone C # 5 sera si géniale que vous n'aurez pas à vous soucier de le faire:
if (InvokeRequired)
{
BeginInvoke(...);
return;
}
// do your stuff here
Il semble que le rappel d'une opération d'attente se produira dans le thread d'origine de l'appelant. Eric Lippert et Anders Hejlsberg ont déclaré à plusieurs reprises que cette fonctionnalité provenait de la nécessité de rendre les interfaces utilisateur (en particulier celles des appareils tactiles) plus réactives.
Je pense qu'une utilisation courante d'une telle fonctionnalité serait quelque chose comme ceci:
public class Form1 : Form
{
// ...
async void GetFurtherInfo()
{
var temperature = await GetCurrentTemperatureAsync();
label1.Text = temperature;
}
}
Si seul un rappel est utilisé, la définition du texte de l'étiquette déclenche une exception car il n'est pas exécuté dans le thread de l'interface utilisateur.
Jusqu'à présent, je n'ai trouvé aucune ressource confirmant que c'est le cas. Est-ce que quelqu'un sait à propos de cela? Existe-t-il des documents expliquant techniquement comment cela fonctionnera?
Veuillez fournir un lien à partir d'une source fiable, ne vous contentez pas de répondre «oui».
la source
await
fonctionnalité. C'est juste beaucoup de sucre syntaxique pour passer la suite . Peut-être y a-t-il d'autres améliorations non liées à WinForms qui sont censées aider? Cela tomberait dans le cadre du .NET lui-même, et non en C # en particulier.Réponses:
Je pense que vous confondez quelques choses ici. Ce que vous demandez est déjà possible à l'aide
System.Threading.Tasks
,async
etawait
en C # 5 vont juste fournir un peu plus de sucre syntaxique pour la même fonctionnalité.Prenons un exemple Winforms - déposez un bouton et une zone de texte sur le formulaire et utilisez ce code:
Exécutez-le et vous verrez que (a) il ne bloque pas le thread d'interface utilisateur et (b) vous n'obtenez pas l'erreur habituelle "opération cross-thread non valide" - sauf si vous supprimez l'
TaskScheduler
argument du dernierContinueWith
, dans auquel cas vous le ferez.C'est standard style de passage de continuation . La magie opère dans la
TaskScheduler
classe et plus précisément dans l'instance récupérée parFromCurrentSynchronizationContext
. Passez cela dans n'importe quelle continuation et vous lui dites que la continuation doit s'exécuter sur le thread appelé laFromCurrentSynchronizationContext
méthode - dans ce cas, le thread d'interface utilisateur.Les attente sont légèrement plus sophistiquées dans le sens où elles savent sur quel thread elles ont commencé et sur quel thread la suite doit se produire. Le code ci-dessus peut donc être écrit un peu plus naturellement:
Ces deux devraient être très similaires, et en fait, ils sont très similaires. le
DelayedAddAsync
méthode retourne maintenant unTask<int>
au lieu d'unint
, et donc leawait
fait de simplement gifler les continuations sur chacun d'eux. La principale différence est qu'elle passe le long du contexte de synchronisation sur chaque ligne, vous n'avez donc pas à le faire explicitement comme nous l'avons fait dans le dernier exemple.En théorie, les différences sont beaucoup plus importantes. Dans le deuxième exemple, chaque ligne de la
button1_Click
méthode est réellement exécutée dans le thread d'interface utilisateur, mais la tâche elle-même (DelayedAddAsync
) s'exécute en arrière-plan. Dans le premier exemple, tout s'exécute en arrière - plan , à l' exception de l'affectation àtextBox1.Text
laquelle nous avons explicitement attaché le contexte de synchronisation du thread d'interface utilisateur.C'est ce qui est vraiment intéressant
await
- le fait qu'un serveur d'attente peut sauter dans et hors de la même méthode sans aucun appel bloquant. Vous appelezawait
, le thread actuel revient au traitement des messages, et quand c'est fait, le serveur reprendra exactement là où il s'était arrêté, dans le même thread qu'il a laissé. Mais en termes de votreInvoke
/BeginInvoke
contraste dans la question, je '' Je suis désolé de dire que vous auriez dû arrêter cela il y a longtemps.la source
ArrayList
classe dans un nouveau code. Je n'ai à peine aucune expérience avec RX, moi-même. Les gens apprennent ce qu'ils ont besoin de savoir et partagent ce qu'ils savent déjà, même si ce qu'ils savent déjà est dépassé. Cette réponse pourrait être obsolète dans quelques années.Oui, pour le thread d'interface utilisateur, le rappel d'une opération d'attente se produira sur le thread d'origine de l'appelant.
Il y a un an, Eric Lippert a écrit une série en 8 parties: Fabulous Adventures In Coding
EDIT: et voici // build / présentation d' Anders : channel9
BTW, avez-vous remarqué que si vous tournez "// build /" à l'envers, vous obtenez "/ plinq //" ;-)
la source
Jon Skeet a fait une excellente présentation couvrant les méthodes Async en C # 5 que vous pouvez trouver extrêmement utile:
http://skillsmatter.com/podcast/home/async-methods
la source