J'essaie depuis un moment d'obtenir quelque chose que je pensais être simple de travailler avec .NET 4.5
Je veux lancer deux tâches longues en même temps et collecter les
résultats de la meilleure façon C # 4.5 (RTM)
Ce qui suit fonctionne mais je n'aime pas ça parce que:
- Je veux
Sleep
être une méthode asynchrone pour pouvoirawait
utiliser d'autres méthodes - Ça a l'air maladroit avec
Task.Run()
- Je ne pense même pas que cela utilise de nouvelles fonctionnalités linguistiques!
Code de travail:
public static void Go()
{
Console.WriteLine("Starting");
var task1 = Task.Run(() => Sleep(5000));
var task2 = Task.Run(() => Sleep(3000));
int totalSlept = task1.Result + task2.Result;
Console.WriteLine("Slept for a total of " + totalSlept + " ms");
}
private static int Sleep(int ms)
{
Console.WriteLine("Sleeping for " + ms);
Thread.Sleep(ms);
Console.WriteLine("Sleeping for " + ms + " FINISHED");
return ms;
}
Code non fonctionnel:
Mise à jour: cela fonctionne réellement et c'est la bonne façon de le faire, le seul problème est le Thread.Sleep
Ce code ne fonctionne pas car l'appel à Sleep(5000)
lance immédiatement la tâche en cours d'exécution et Sleep(1000)
ne s'exécute donc pas tant qu'elle n'est pas terminée. C'est vrai même si Sleep
c'est le cas async
et je n'utilise pas await
ou n'appelle pas .Result
trop tôt.
J'ai pensé qu'il y avait peut-être un moyen d'obtenir un non-en cours Task<T>
d' exécution en appelant une async
méthode afin que je puisse ensuite appeler Start()
les deux tâches, mais je ne peux pas comprendre comment obtenir un en Task<T>
appelant une méthode asynchrone.
public static void Go()
{
Console.WriteLine("Starting");
var task1 = Sleep(5000); // blocks
var task2 = Sleep(1000);
int totalSlept = task1.Result + task2.Result;
Console.WriteLine("Slept for " + totalSlept + " ms");
}
private static async Task<int> Sleep(int ms)
{
Console.WriteLine("Sleeping for " + ms);
Thread.Sleep(ms);
return ms;
}
la source
task1.Result
pas àvar task1 = Sleep(5000)
car votre méthode Sleep sans mot-clé d'attente est synchrone.Réponses:
Vous devez utiliser Task.Delay au lieu de Sleep pour la programmation asynchrone, puis utiliser Task.WhenAll pour combiner les résultats de la tâche. Les tâches seraient exécutées en parallèle.
la source
la source
Go
méthode de l'appelant est synchrone, mais que vous souhaitez effectuer deux tâches indépendantes de manière asynchrone (c'est-à-dire qu'aucune n'a besoin de se terminer avant l'autre, mais que les deux doivent se terminer avant que les exécutions continuent), ceTask.WaitAll
serait mieux, et vous ne Pas besoin du mot-clé await, donc pas besoin que laGo
méthode appelante soit elle-même asynchrone. Aucune des deux approches n'est meilleure, c'est juste une question de quel est votre objectif.async void LongTask1() {...}
n'a pas de propriété Task.Result. Utilisez la tâche sans T dans ce cas:async Task LongTask1()
.Task<TResult> t1 = LongTask1();
et maintenant je reçoist1.Result
.<TResult>
est le type de retour de votre résultat. Vous aurez besoin d'unreturn <TResult>
dans votre méthode pour que cela fonctionne.t1
et det2
variables, vous pouvez utilisernew Task(...)
. Par exemple:int int1 = 0; await Task.WhenAll(new Task(async () => { int1 = await LongTask1(); }));
. Un problème de cette approche est que le compilateur ne reconnaîtra pas que la variable a été assignée et la traitera comme non assignée si vous ne lui donnez pas de valeur initiale.Bien que votre
Sleep
méthode soit asynchrone, ceThread.Sleep
n'est pas le cas. L'idée générale de l'async est de réutiliser un seul thread, et non de démarrer plusieurs threads. Parce que vous avez bloqué à l'aide d'un appel synchrone à Thread.Sleep, cela ne fonctionnera pas.Je suppose que
Thread.Sleep
c'est une simplification de ce que vous voulez réellement faire. Votre implémentation réelle peut-elle être codée en tant que méthodes asynchrones?Si vous avez besoin d'exécuter plusieurs appels de blocage synchrones, regardez ailleurs je pense!
la source
var x = y()
, et nonvar x=await y()
ouy().wait()
encore encore attendez jusqu'au bout, et si async ne gère pas cela tout seul, que dois-je faire? Notez que y est décoré avec async, et je m'attends à ce qu'il fasse tout dans le quand tout, pas exactement là où il est assigné, EDIT: je viens de dire à mon partenaire, essayonsTask.Factory
, et il a dit que cela fonctionnait quand je m'éclate côté de cette classePour répondre à ce point:
vous pouvez peut-être réécrire la
Sleep
fonction comme ceci:l'exécution de ce code produira:
la source
C'est le week - end maintenant!
la source
Cet article a permis d'expliquer beaucoup de choses. C'est dans le style FAQ.
FAQ sur Async / Await
Cette partie explique pourquoi
Thread.Sleep
fonctionne sur le même fil d'origine - menant à ma confusion initiale.la source