en attente de tâche avec un délai d'attente
Je suis en train d'écrire une méthode d'aide qui me permet de passer en un point arbitraire de la tâche et un délai d'attente. Si la tâche est terminée avant que le délai, un succès délégué est appelé, sinon une erreur délégué est appelé. La méthode ressemble à ceci:
public static async Task AwaitWithTimeout(Task task, int timeout, Action success, Action error)
{
if (await Task.WhenAny(task, Task.Delay(timeout)) == task)
{
if (success != null)
{
success();
}
}
else
{
if (error != null)
{
error();
}
}
}
Maintenant ce semble de travail la plupart du temps, mais je voulais écrire quelques tests pour vous en assurer. Ce test, à ma grande surprise, échoue, et appelle l'erreur délégué au lieu de la réussite:
var taskToAwait = Task.Delay(1);
var successCalled = false;
await TaskHelper.AwaitWithTimeout(taskToAwait, 10, () => successCalled = true, null);
Assert.IsTrue(successCalled);
Ce test, cependant, est vert:
var taskToAwait = Task.Run(async () =>
{
await Task.Delay(1);
});
var successCalled = false;
await TaskHelper.AwaitWithTimeout(taskToAwait, 10, () => successCalled = true, null);
Assert.IsTrue(successCalled);
Comment dois-je faire à la fois des tests de vert? Mon utilisation de la Tâche.WhenAny incorrect?
Delay(1)
est très court (surtout si vous êtes de débogage) - départ sur thread séparé de la rendre suffisamment long pour votre test à passer la plupart du temps. Essayez d'utiliser plus de retard ou, mieux encore, tâche qui permet de remplir à la main synchrone, il en test.OriginalL'auteur user1202032 | 2016-02-26
Vous devez vous connecter pour publier un commentaire.
Minuteurs sont inexactes. Par défaut, leur précision est d'environ 15 ms. Quelque chose de plus bas que cela va déclencher dans 15ms intervalle. Reportez-vous liés réponse.
Étant donné que vous avez 1ms minuterie et 10ms minuterie; les deux sont à peu près égales, de sorte que vous obtenez des résultats incohérents.
Le code que vous avez enveloppé dans
Task.Run
et prétend être le travail, c'est juste une coïncidence. Quand j'ai essayé plusieurs fois, les résultats sont contradictoires. Il échoue parfois pour la même raison mentionnée.Vous êtes mieux de l'augmentation du délai d'attente ou de passer dans un déjà terminé la tâche.
Par exemple de test suivant doit constamment passer. Rappelez-vous que votre essai doit être conforme non fragile.
Pour tâche éternelle utilisation
TaskCompletionSource
et de ne pas définir son résultat.Aussi je vous recommande d'éviter d'utiliser
null
. Vous pouvez simplement transmettre le vide délégué en tant que paramètre. Ensuite, vous ne voulez pas avoir la valeur null vérifie éparpillés sur votre base de code.Allais-je écrire la méthode d'assistance que:
Noter que la méthode ci-dessus est une méthode d'extension; de sorte que vous pouvez l'appeler avec instance de la tâche.
Assurez-vous. Mise à jour de ma réponse à l'adresse tâche éternelle.
Alors que le concept de base (à l'aide de
Task.WhenAny
attendre deux tâches) est sur place, l'API autour d'elle se sent sale.Action
de réussite est en désordre si vous avez besoin de fil d'une autreTask
- vous finirais avec laide de capture. Je serais tout simplement jeter unTimeoutException
dans le délai de scénario et de traiter la réussite comme de la réussite. Dans la performance des cas critiques, unTask<bool>
type de retour également de travailler (oùtrue
moyens de la réussite etfalse
moyens de délai d'attente).Puis il y a aussi la manipulation de la réalisation éventuelle du délai
Task
(discuté ici: blogs.msdn.com/b/pfxteam/archive/2012/10/05/...). Et, bien sûr, n'oubliez pasConfigureAwait(false)
- il n'y a absolument aucune raison de ne pas l'avoir dans l'aide ou des méthodes de bibliothèques.Oui exactement mes pensées.
Task<bool>
plus de sens que les délégués. Encore mieux TimeoutExceptiion. Je laisse à l'OP.OriginalL'auteur Sriram Sakthivel