2010-11-22 5 views
100

J'implémente une méthode Task<Result> StartSomeTask() et je connais déjà le résultat avant que la méthode ne soit appelée. Comment créer un Task<T> déjà terminé?Créer une tâche terminée <T>

C'est ce que je suis en train de faire:

private readonly Result theResult = new Result(); 

public override Task<Result> StartSomeTask() 
{ 
    var task = new Task<Result>(() => theResult); 
    task.RunSynchronously(CurrentThreadTaskScheduler.CurrentThread); 
    return task; 
} 

est-il une meilleure solution?

+6

Remarque, les réponses à cette question fonctionne aussi bien pour la création d'une tâche simple (non ) parce que la tâche hérite de la tâche. –

Répondre

102
private readonly Result theResult = new Result(); 

public override Task<Result> StartSomeTask() 
{ 
    var taskSource = new TaskCompletionSource<Result>(); 
    taskSource.SetResult(theResult); 
    return taskSource.Task; 
} 
162

Lorsque vous ciblez .NET 4.5, vous pouvez utiliser Task.FromResult:

public static Task<TResult> FromResult<TResult>(TResult result); 

Pour créer une tâche ayant échoué, utilisez Task.FromException:

public static Task FromException(Exception exception); 
public static Task<TResult> FromException<TResult>(Exception exception); 

4,6 .NET ajoute Task.CompletedTask si vous avez besoin d'un non générique Task.

public static Task CompletedTask { get; } 

pour Contournements les anciennes versions de .NET:

  • Lorsque vous ciblez .NET 4.0 avec Async Ciblage pack (ou AsyncCTP) vous pouvez utiliser TaskEx.FromResult à la place.

  • Pour obtenir non générique Task avant .NET 4.6, vous pouvez utiliser le fait que Task<T> dérive de Task et il suffit d'appeler Task.FromResult<object>(null) ou Task.FromResult(0).

+13

Pour retourner une tâche non générique, il est préférable d'utiliser quelque chose comme Task.FromResult (0). L'utilisation de "null" comme paramètre peut confondre le compilateur qui ne peut pas déterminer le paramètre générique. – Whyllee

+0

Qu'en est-il des exceptions? Les méthodes asynchrones sont compilées dans la machine d'état qui intercepte les exceptions et les enregistre dans la tâche renvoyée. Cela arrive même pour le code en cours d'exécution avant la première attente. Méthode retournant Task.FromResult peut lancer des exceptions directement. –

+0

@ RobertVažan Un cas de bord intéressant. On peut soutenir que si vous récupérez votre _ result result_ d'une méthode et que cette méthode génère des exceptions, alors il y a un défaut à corriger. – Gusdor

1

Si vous utilisez Rx, une alternative est Observable.Retour (résultat) .ToTask().

12

Pour les tâches sans valeur de retour, .NET 4.6 a ajouté Task.CompletedTask.

Il renvoie une tâche qui est déjà dans TaskStatus.RanToCompletion. Il renvoie probablement la même instance à chaque fois, mais la documentation vous avertit de ne pas compter sur ce fait.

0

Calling Task.WhenAll sans aucun paramètre retournera une tâche terminée.

Task task = Task.WhenAll(); 
Questions connexes