Exécuter la méthode "async" sur un thread d'arrière-plan
Je suis en train de lancer un "async" méthode à partir d'une méthode ordinaire:
public string Prop
{
get { return _prop; }
set
{
_prop = value;
RaisePropertyChanged();
}
}
private async Task<string> GetSomething()
{
return await new Task<string>( () => {
Thread.Sleep(2000);
return "hello world";
});
}
public void Activate()
{
GetSomething.ContinueWith(task => Prop = task.Result).Start();
//^ exception here
}
L'exception renvoyée est:
De démarrage ne peut pas être appelé sur une poursuite de la tâche.
Ce que ça veut dire, de toute façon? Comment puis-je exécuter simplement ma méthode asynchrone sur un thread d'arrière-plan, envoyer le résultat dans le thread de l'INTERFACE utilisateur?
Modifier
Aussi essayé Task.Wait
mais l'attente n'en finit pas:
public void Activate()
{
Task.Factory.StartNew<string>( () => {
var task = GetSomething();
task.Wait();
//^ stuck here
return task.Result;
}).ContinueWith(task => {
Prop = task.Result;
}, TaskScheduler.FromCurrentSynchronizationContext());
GetSomething.ContinueWith(task => Prop = task.Result).Start();
}
source d'informationauteur McGarnagle
Vous devez vous connecter pour publier un commentaire.
Pour fixer votre exemple particulier:
Cela va fonctionner, mais c'est de la vieille école.
Le moyen moderne de faire quelque chose sur un thread d'arrière-plan et de l'expédition de retour à la thread de l'INTERFACE utilisateur est d'utiliser
Task.Run()
async
etawait
:Task.Run
va commencer quelque chose dans un thread du pool. Lorsque vousawait
quelque chose, automatiquement, il revient sur le contexte d'exécution qui a commencé. Dans ce cas, votre thread de l'INTERFACE utilisateur.Vous devriez généralement de ne jamais avoir à appeler
Start()
. Préférezasync
méthodes,Task.Run
etTask.Factory.StartNew
qui tous démarrer les tâches automatiquement. Les Continuations créé avecawait
ouContinueWith
sont également démarré automatiquement lorsque leurs parents se termine.AVERTISSEMENT sur l'utilisation FromCurrentSynchronizationContext:
Ok, Cory sait comment me faire réécrire réponse:).
De sorte que le principal coupable est en fait le FromCurrentSynchronizationContext!
Tout moment StartNew ou ContinueWith fonctionne sur ce type de planificateur, il fonctionne sur le Thread de l'INTERFACE utilisateur. On peut le penser:
OK, nous allons commencer les opérations suivantes sur l'INTERFACE utilisateur, le changement de certains contrôles, la réapparition de certaines opérations. Mais à partir de maintenant TaskScheduler.Courant n'est pas nul et si aucun contrôle a certains événements, qui se reproduisent certains StartNew, s'attendant à être en cours d'exécution sur ThreadPool, puis à partir de là, il va mal. L'INTERFACE utilisateur de l'aps sont généralement complexes, le malaise de maintenir la certitude, que rien ne va en appeler une autre StartNew l'opération, simple exemple ici:
Veuillez notez que les tâches retourné par:
ne peut pas être démarré! Ils sont déjà bien chaudes tâches...