Comment forcer les substitutions enfants asynchrones dans C # 5.0

Je travaille sur un système dans lequel plusieurs objects client sont supposés implémenter une fonction particulière via une interface, et je souhaite que cette fonction s’exécute de manière asynchrone avec les continuations (les implémentations doivent être liées aux E / S et assurez-vous que tous les objects client remplissent cette fonction dès que possible). J’utilise le rafraîchissement CTP Visual Studio Async pour SP1, avec C # “5.0”.

Quelle est la pratique recommandée pour appliquer un comportement asynchrone dans les objects enfants de ma classe abstraite (voir ci-dessous)? Je ne peux pas (apparemment) imposer l’utilisation de méthodes “asynchrones” en utilisant l’approche de la méthode virtuelle. Je ne peux exiger qu’un type de retour ‘Tâche’. Est-ce que cela signifie que je ne devrais pas essayer d’exiger un comportement asynchrone du tout dans les objects enfants? Dans ce cas, le type de retour devrait-il être simplement “nul”?

L’interface publique est une conséquence malheureuse de la conception du système en ce moment, mais c’est un problème distinct. De toute évidence, je ne pouvais pas contraindre quiconque à être asynchrone qui contourne ‘BaseFoo’ et implémente simplement l’interface ‘IFoo’.

Voici le code:

public interface IFoo { void Bar(); //NOTE: Cannot use 'async' on methods without bodies. } public abstract class BaseFoo : IFoo { public async void Bar() { await OnBar(); //QUESTION: What is the right "async delegation" pattern? } protected virtual async Task OnBar() { await TaskEx.Yield(); } } public class RealFoo : BaseFoo //NOTE: May be implemented by 3rd party { protected override async Task OnBar() { //CLIENT: Do work, potentially awaiting async calls await TaskEx.Yield(); //SECONDARY QUESTION: Is there a way to avoid this if there are no 'awaits' in the client's work? } } 

Si une méthode est implémentée en utilisant async / await ou not est un détail d’ implémentation . Comment la méthode doit se comporter est un détail de contrat, qui doit être spécifié de la manière habituelle.

Notez que si vous faites en sorte que la méthode retourne une Task ou une Task , il est plus évident qu’elle est asynchrone et sera probablement difficile à implémenter sans être asynchrone.

D’un autre côté, s’il y a une implémentation (par exemple à des fins de test) où les expressions d’attentes ne seraient jamais incomplètes, pourquoi voudriez-vous forcer quelqu’un à écrire une méthode asynchrone sans aucune await ? Vous vous attendez à ce que les implémentations soient liées aux IO, mais peut-être y aura-t-il des cas particuliers où les implémentations voudront utiliser des données codées en dur, etc.

Fondamentalement, vous devez gérer cela dans la documentation de la méthode – si vous ne pouvez pas faire confiance aux développeurs pour lire cela, vous n’avez aucune chance de toute façon 🙁

En plus de la réponse de Jon, si vous suivez le modèle asynchrone basé sur les tâches, vos noms de méthode doivent être suffixés avec Async , qui indique qu’il s’agit d’une méthode asynchrone.

Si vous implémentez une interface

 public interface IFoo { Task BarAsync(); } 

il devrait être évident que cela devrait être implémenté avec le mot-clé async .