sincrono sharp programming programacion net example ejemplos ejemplo await async asincrona c# asynchronous synchronous .net-4.5 async-await

sharp - C#tiene función síncrona llamada asíncrona función o función asíncrona llamada síncrona función



task await c# ejemplo (3)

Estoy escribiendo una biblioteca de C # .Net 4.5 para realizar operaciones comunes de base de datos SQL (copia de seguridad, restauración, ejecución de secuencias de comandos, etc.). Quiero tener funciones síncronas y asíncronas para cada operación, ya que esta consola será utilizada tanto por la consola como por las aplicaciones GUI, pero no quiero duplicar el código en todas partes. Así que como lo veo, tengo dos opciones:

  1. Escriba el código que hace el trabajo en una función síncrona, y luego envuélvalo en una tarea para la función asíncrona, así:

    public void BackupDB(string server, string db) { // Do all of the work and long running operation here } public async Task BackupDBAsync(string server, string db) { await Task.Factory.StartNew(() => BackupDB(server, db)).ConfigureAwait(false); }

  2. Escriba el código que hace el trabajo en una función asíncrona y llámelo desde una función síncrona usando .Wait ():

    public async Task BackupDBAsync(string server, string db) { // Do all of the work and long running operation here, asynchronously. } public void BackupDB(string server, string db) { BackupDBAsync(server, db).Wait(); // Execution will wait here until async function finishes completely. }

¿Es una opción mejor que la otra? ¿Es una de las mejores prácticas? ¿O hay otras alternativas (mejores)?

Sé que una advertencia al usar .Wait () es que todas las sentencias de espera en la función asíncrona tienen que usar .ConfigureAwait (false) para evitar puntos muertos ( como se explica aquí ), pero ya que estoy escribiendo una biblioteca que nunca Necesito acceder a la UI o al WebContext. Estoy seguro de hacerlo.

Notaré también que la biblioteca de SQL también tiene funciones síncronas y asíncronas que se pueden usar, por lo que si hago el trabajo en la función de sincronización, llamaría a su función de sincronización, y si hago el trabajo en la función asíncrona, Llamaría a su función asíncrona.

Se aprecian pensamientos / sugerencias.

- edit: también publiqué esta pregunta en los foros de MSDN para intentar obtener una respuesta oficial de MS -


Quiero tener funciones síncronas y asíncronas para cada operación, ya que esta consola será utilizada tanto por la consola como por las aplicaciones GUI, pero no quiero duplicar el código en todas partes.

La mejor respuesta es: no.

Stephen Toub tiene dos excelentes publicaciones de blog sobre este tema:

Él recomienda exponer los métodos asíncronos como asíncronos, y los métodos síncronos como síncronos. Si necesita exponer ambos, encapsule la funcionalidad común en métodos privados (síncronos) y duplique las diferencias asíncronas / sincronizadas.


No parece haber un punto para simplemente marcar un método como asíncrono sin usar una espera. Marcarlo como asíncrono no lo hace asíncrono, le permite utilizar espera (el código ejecutado en espera es lo que sucede de forma asíncrona, y luego el resto del método asíncrono también se hará de forma asíncrona) en el cuerpo del método:

Normalmente, un método modificado por la palabra clave async contiene al menos una expresión o declaración de espera. El método se ejecuta de forma síncrona hasta que alcanza la primera expresión de espera, momento en el que se suspende hasta que se completa la tarea esperada. Mientras tanto, el control se devuelve al llamador del método. Si el método no contiene una expresión o declaración de espera, se ejecuta de forma síncrona. Una advertencia del compilador lo alerta sobre cualquier método asíncrono que no contenga la espera porque esa situación podría indicar un error. Para más información, vea la advertencia CS4014 del compilador.

Desde: async


Tuve una situación similar en la que algunas aplicaciones necesitaban que los datos se cargaran de forma sincrónica y otras asyc. Decidí crear una interfaz que llamé mi cargador de datos:

public interface IIMViewModelDL { void LoadProjects(AssignProjects callback); }

La devolución de llamada de AssignProjects es solo un simple delegado que toma en la lista de proyectos devueltos:

public delegate void AssignProjects(IEnumerable<Project> results);

Ahora, la belleza de esto es que puede trabajar con la interfaz sin saber si está tratando en sincronización o asíncrono.

Se crean tres clases: una base, una sincronización y una asíncrona:

public abstract class BaseViewModelDL { protected IEnumerable<Project> LoadProjects() { BaseServiceClient client = new BaseServiceClient(); return client.Projects(); } public class SynchronousViewModelDL : BaseViewModelDL, IIMViewModelDL { public void LoadProjects(AssignProjects callback) { callback(base.LoadProjects()); } public class AsyncIMViewModelDL : BaseViewModelDL, IIMViewModelDL { public void LoadProjects(AssignProjects callback) { BackgroundWorker loadProjectsAsync = new BackgroundWorker(); loadProjectsAsync.DoWork += new DoWorkEventHandler(LoadProjectsAsync_DoWork); loadProjectsAsync.RunWorkerCompleted += new RunWorkerCompletedEventHandler(LoadProjectsAsync_RunWorkerCompleted); loadProjectsAsync.RunWorkerAsync(callback); } void LoadProjectsAsync_DoWork(object sender, DoWorkEventArgs e) { var results = new ObservableCollection<Project>(base.LoadProjects()); e.Result = new object[] { results, e.Argument }; } void LoadProjectsAsync_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { AssignProjects callback = (AssignProjects)((object[])e.Result)[1]; IEnumerable<Project> results = (IEnumerable<Project>)((object[])e.Result)[0]; callback(results); }

Ahora, en su aplicación, puede decidir cómo desea cargar los datos ... esto podría inyectarse a través de un contenedor IoC, pero está codificado para fines de demostración:

private ViewModelDataLoaders.IIMViewModelDL dataLoader = new ViewModelDataLoaders.AsyncIMViewModelDL();

Ahora, su código de llamada tiene el mismo aspecto y no se sabe si es asíncrono o sincronizado:

private void LoadProjects() { dataLoader.LoadProjects( delegate(IEnumerable<Project> results) { Projects = new ObservableCollection<Project>(results); }); }

Lo uso regularmente para pruebas unitarias (sincronización), aplicaciones WPF (asíncronas) y aplicaciones de consola (sincronización).