Pregunta ¿Cómo mezclar de forma segura sincronización y código asíncrono?


Tengo esta biblioteca que es puramente sincronizada. Expone los métodos de sincronización y tengo clientes que lo usan.

Cambié la implementación subyacente a asincrónica y expuse los métodos asíncronos para quien quiera usarla. Pero ahora tengo un montón de código replicado. El código asíncrono parece funcionar mejor. Me gustaría que los clientes existentes lo aprovechen y quiero eliminar la repetición del código.

¿Hay alguna manera segura de mantener una firma de sincronización y llamar a la implementación asincrónica?

Tengo miedo específicamente a los bloqueos cuando llamo .Result y .Esperar.


13
2018-06-18 22:59


origen


Respuestas:


Te aliento fuertemente no hacer esto

Primero, lee ¿Debo exponer envolturas sincrónicas para métodos asíncronos? y ¿Debería exponer las envolturas asincrónicas para los métodos sincrónicos? por Stephan Toub.

Las principales razones por las que no haría esto:

  1. Sincronización sobre Async - Como dijiste, puntos muertos. Más alto o más bajo en la cadena de llamadas, usando Result o Wait en asincronía tal vez negocios arriesgados. Realmente depende de qué plataforma se ejecute (ASP.NET, UI, consola) ya que cada uno se comporta de una manera un poco diferente (incluso cuando se usa ConfigureAwait(false))

  2. Async sobre sincronización - Escalabilidad. Una vez que veo un punto final asíncrono, supongo que es pura asincronía, que para mí, como consumidor de la API, significa que no hay ningún hilo girando "detrás de mi espalda". Si los usuarios suponen lo mismo, descubrir que por cada llamada a un método asíncrono se utiliza un subproceso de grupo de subprocesamiento puede dañar drásticamente el rendimiento al intentar escalar. Si los usuarios desean ajustar un método de sincronización con un Task.Run, deja que ellos hagan esa llamada y hacer su juicio sobre cómo afectará esto a su aplicación


14
2018-06-19 03:43



Intenta comenzar de abajo hacia arriba, o te encuentras con puntos muertos (

Las aplicaciones de la consola se comportan de forma diferente a las aplicaciones web y de interfaz de usuario en cuanto a cómo manejan los interbloqueos si NO se manejan adecuadamente. Si está utilizando MVC, use una tarea asíncrona ActionResult y ajuste llamadas síncronas específicas en Task.Run ((= => SYNCCODE) usando async y aguarde. Proceso similar con código UI, que utiliza métodos async / await upon event (como Click event handlers).

Normalmente cierro mis llamadas de sincronización con versiones asíncronas y las manejo como tareas. Si esos métodos de sincronización pueden utilizar versiones Async de métodos .NET, trato de ir "más adentro" siempre que sea posible.


3
2018-06-18 23:27