Comment mélanger en toute sécurité le code synchrone et asynchrone?

J’ai cette bibliothèque qui est purement sync. Il expose les méthodes de synchronisation et j’ai des clients qui l’utilisent.

J’ai changé l’implémentation sous-jacente en async et exposé des méthodes async pour ceux qui veulent l’utiliser. Mais maintenant, j’ai beaucoup de code répliqué. Le code asynchrone semble mieux fonctionner. J’aimerais que les clients existants en profitent et je veux éliminer la répétition de code.

Existe-t-il un moyen sûr de conserver une signature de synchronisation et d’appeler l’implémentation asynchrone?

J’ai particulièrement peur des blocages lorsque j’appelle .Result et .Wait.

Je vous encourage fortement à ne pas faire cela

D’abord, lisez Dois-je exposer les wrappers synchrones pour les méthodes asynchrones? et Dois-je exposer les wrappers asynchrones pour les méthodes synchrones? par Stephan Toub.

Les principales raisons pour lesquelles je ne ferais pas ceci:

  1. Synchroniser sur Async – Comme vous l’avez dit, les blocages. Plus haut ou plus bas dans la chaîne d’appels, utiliser Result ou Wait de manière asynchrone peut constituer un travail risqué. Cela dépend vraiment de la plate-forme que vous utilisez (ASP.NET, UI, Console), car chacune se comporte un peu différemment (même en utilisant ConfigureAwait(false) )

  2. Async over Sync – Évolutivité. Une fois que je vois un sharepoint terminaison asynchrone, je suppose que c’est du pur async, ce qui pour moi, en tant que consommateur de l’API, signifie qu’il n’y a pas de fil qui tourne “derrière mon dos”. Si vos utilisateurs supposent la même chose, savoir que l’utilisation d’un thread de pool de threads pour chaque appel d’une méthode asynchrone peut nuire considérablement aux performances lorsque vous essayez de faire évoluer votre système. Si les utilisateurs souhaitent Task.Run une méthode de synchronisation avec un Task.Run , laissez-leur le Task.Run de passer cet appel et de déterminer si cela affectera leur application.

Essayez de commencer par le bas, ou vous rencontrez des impasses (

Les applications de console se comportent différemment des applications Web et d’interface utilisateur en ce qui concerne la façon dont elles gèrent les blocages si elles ne sont pas gérées correctement. Si vous utilisez MVC, utilisez une tâche asynchrone ActionResult et encapsulez des appels synchrones spécifiques sur Task.Run (() => SYNCCODE) en utilisant async et attendez. Processus similaire avec du code d’interface utilisateur, utilisant des méthodes d’événement asynchrone / wait upon (telles que des gestionnaires d’événements Click).

En règle générale, j’enveloppe mes appels de synchronisation avec des versions asynchrones et les traite en tant que tâches. Si ces méthodes de synchronisation peuvent utiliser des versions asynchrones des méthodes .NET, j’essaie d’aller «plus loin» dans la mesure du possible.