52 votes

Interfaces et méthodes asynchrones

J'ai une demande. Cette application utilise une interface pour accéder à la base de données. Cette interface peut être implémentée par de nombreuses classes. Par exemple, une classe utilise EF 4.4, mais d'autres classes peuvent utiliser EF5 qui est plus efficace. Dans le futur, j'utiliserai peut-être EF6 car il utilise des méthodes asynchrones. Dans cet exemple, toutes les méthodes utilisent EF, mais peut-être d'autres options peuvent être utilisées d'autres façons.

L'application est codée une fois, en utilisant l'interface, et selon le fichier de configuration, utiliser une implémentation ou l'autre, donc je dois seulement modifier le code à un endroit, le constructeur, pour ajouter la nouvelle option dans l'instanciation de la classe qui est assignée à l'interface.

Pour le moment, toutes les méthodes des classes ne sont pas async mais à l'avenir, si j'utilise EF6, j'aimerais utiliser les méthodes asynchrones. Je ne sais donc pas s'il est possible que la classe qui utilise EF6 et qui implémente l'interface puisse utiliser la méthode asynchrone. async méthodes.

Pour les méthodes asynchrones de EF6, j'utiliserais le modèle async/awiat, donc dans la méthode de ma classe je dois utiliser l'attribut async. Cela me permet d'utiliser la méthode await lorsque j'appelle la méthode asynchrone de EF6.

Mais cette classe peut implémenter l'interface qui, dans un premier temps, est destinée aux méthodes synchrones ?

Existe-t-il un moyen d'utiliser plusieurs implémentations dans l'application principale sans devoir modifier le code ? Certaines implémentations utiliseront des méthodes asynchrones tandis que d'autres seront synchrones.

3 votes

Gardez à l'esprit que async ne fait pas partie de la signature ; une méthode asynchrone et une méthode non asynchrone peuvent toutes deux implémenter la même méthode d'interface.

1 votes

Ce n'est pas la méthode qui est attendable, c'est le type (de retour).

2 votes

Trop d'explications pour une simple question. IMHO.

62voto

Servy Points 93720

async ne fait pas partie de la signature, donc vous n'avez pas besoin de vous préoccuper de savoir si la méthode implémentant l'interface est async ou non, vous ne devez vous préoccuper que des types de propriétés, du type de retour, du nom de la méthode et de l'accessibilité.

El réel différence est que votre async devront retourner un Task ou un Task<T> alors que les méthodes non-asynchrones renvoient très probablement les résultats suivants void ou autre, T directement.

Si vous voulez que votre application soit à l'épreuve du temps, vous pouvez faire en sorte que toutes vos interfaces renvoient les données de l'utilisateur. Task o Task<T> et que, pour vos implémentations EF4/EF5, vous enveloppiez vos résultats dans une tâche terminée, même s'ils sont exécutés de manière synchrone.

Task.FromResult a été ajouté dans .NET 4.5, mais si vous ne l'avez pas, vous pouvez écrire le vôtre assez facilement :

public static Task<T> FromResult<T>(T result)
{
    var tcs = new TaskCompletionSource<T>();
    tcs.SetResult(result);
    return tcs.Task;
}

Vous pouvez également écrire un CompletedTask qui renvoie simplement une tâche qui s'est déjà terminée : (Elle met en cache une seule tâche pour des raisons d'efficacité).

private static Task _completedTask;
public static Task CompletedTask()
{
    return _completedTask ?? initCompletedTask();
}

private static Task initCompletedTask()
{
    var tcs = new TaskCompletionSource<object>();
    tcs.SetResult(null);
    _completedTask = tcs.Task;
    return _completedTask;
}

Ces deux méthodes simplifieront le fait que toutes vos méthodes renvoient un type d'information de type Task bien que cela rende votre code un peu plus désordonné jusqu'à ce que vous puissiez utiliser C# 5.0 pour être capable de await le résultat.

0 votes

Donc la seule solution est de forcer toutes les classes à retourner une tâche ?

1 votes

Eh bien, ce n'est pas le sólo solution. C'est la meilleure que j'ai pu trouver. Si vous disposez de C# 5.0 mais pas de EF 6.0, vous pouvez toujours await les résultats de l'appel de la méthode (même s'ils sont déjà terminés) ce qui rendrait la chose pas trop terrible.

7 votes

Dans une situation comme celle-ci (où vos opérations sont naturellement asynchrones), vous pouvez soit faire en sorte que toutes les méthodes retournent Task ou créer des méthodes synchrones et asynchrones côte à côte.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X