Creo que la verdad es ambigua incluso en la documentación de Microsoft:
En Visual Studio 2012 y .NET Framework 4.5, cualquier método que se atribuya con la async
palabra clave ( Async
en Visual Basic) se considera un método asincrónico, y los compiladores de C # y Visual Basic realizan las transformaciones necesarias para implementar el método de forma asincrónica mediante TAP. Un método asincrónico debe devolver Task
un Task<TResult>
objeto o un objeto.
http://msdn.microsoft.com/en-us/library/hh873177(v=vs.110).aspx
Eso ya no está bien. Cualquier método con async
es asincrónico y luego dice que debe devolver un Task
o Task<T>
, lo que no es correcto para los métodos en la parte superior de una pila de llamadas, Button_Click por ejemplo, o async void
.
Por supuesto, hay que considerar cuál es el objetivo de la convención.
Se podría decir que la Async
convención de sufijos es comunicar al usuario de la API que el método está disponible. Para que un método sea de espera, debe regresar Task
para un Task<T>
método vacío o para un método de devolución de valor, lo que significa que solo el último puede tener el sufijo Async
.
O podría decir que la Async
convención de sufijos es comunicar que el método puede regresar inmediatamente, abandonando el hilo actual para realizar otro trabajo y potencialmente causando carreras.
Esta cita de Microsoft doc dice:
Por convención, agrega "Async" a los nombres de los métodos que tienen un modificador Async o async.
http://msdn.microsoft.com/en-us/library/hh191443.aspx#BKMK_NamingConvention
Lo cual ni siquiera menciona que sus propios métodos asincrónicos que regresan Task
necesitan el Async
sufijo, que creo que todos estamos de acuerdo en que lo hacen.
Entonces, la respuesta a esta pregunta podría ser: ambos. En ambos casos, debe agregar Async
métodos con la async
palabra clave y que devuelvan Task
o Task<T>
.
Le voy a pedir a Stephen Toub que aclare la situación.
Actualizar
Así que lo hice. Y esto es lo que escribió nuestro buen hombre:
Si un método público devuelve una tarea y es de naturaleza asíncrona (a diferencia de un método que se sabe que siempre se ejecuta de forma síncrona hasta su finalización, pero que aún devuelve una tarea por alguna razón), debe tener un sufijo "Asíncrono". Esa es la pauta. El objetivo principal aquí con la denominación es hacer que sea muy obvio para un consumidor de la funcionalidad que el método que se invoca probablemente no completará todo su trabajo de forma sincrónica; por supuesto, también ayuda con el caso en el que la funcionalidad se expone con métodos sincrónicos y asincrónicos, de modo que necesita una diferencia de nombre para distinguirlos. La forma en que el método logra su implementación asincrónica es irrelevante para la denominación: si async / await se usa para obtener la ayuda del compilador, o si los tipos y métodos de System.Threading.Tasks se usan directamente (p. Ej. gramo. TaskCompletionSource) realmente no importa, ya que eso no afecta la firma del método en lo que respecta al consumidor del método.
Por supuesto, siempre hay excepciones a una guía. El más notable en el caso de la asignación de nombres serían los casos en los que la razón de ser de un tipo completo es proporcionar una funcionalidad centrada en async, en cuyo caso tener Async en cada método sería excesivo, por ejemplo, los métodos en Task en sí que producen otras Tasks. .
En cuanto a los métodos asincrónicos de devolución de vacío, no es deseable tenerlos en un área de superficie pública, ya que la persona que llama no tiene una buena forma de saber cuándo se ha completado el trabajo asincrónico. Sin embargo, si debe exponer públicamente un método asincrónico de retorno vacío, es probable que desee tener un nombre que transmita que se está iniciando el trabajo asincrónico, y podría usar el sufijo "Async" aquí si tiene sentido. Dado lo raro que debería ser este caso, diría que en realidad es una decisión caso por caso.
Espero que eso ayude, Steve
La guía sucinta de la oración inicial de Stephen es bastante clara. Excluye async void
porque es inusual querer crear una API pública con tal diseño, ya que la forma correcta de implementar un vacío asincrónico es devolver una Task
instancia simple y dejar que el compilador haga su magia. Sin embargo, si desea un public async void
, Async
se recomienda agregarlo . Otros async void
métodos de primer nivel, como los controladores de eventos, generalmente no son públicos y no importan / califican.
Para mí, me dice que si me pregunto sobre cómo agregar Async
un sufijo a un async void
, probablemente debería convertirlo en un async Task
para que las personas que llaman puedan esperarlo y luego agregarlo Async
.