C # tiene la función de función ASYNC Función síncrona o función síncrona llamada de la función Async

StackOverflow https://stackoverflow.com//questions/11674073

Pregunta

Estoy escribiendo una biblioteca C # .NET 4.5 para realizar operaciones de base de datos SQL comunes (copia de seguridad, restauración, ejecutar script, etc.). Quiero tener funciones tanto sincrónicas como asíncronas para cada operación, ya que esta biblioteca será utilizada por las aplicaciones de la consola y la 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 realice el trabajo en una función síncrona, y luego solo envuelva en una tarea para la función ASYNC, como SO:

    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ámela de 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 práctica una mejor? ¿O hay alguna otra alternativa (mejor)?

    Sé que una advertencia para usar .wait () es que todas las declaraciones esperadas en la función de ASYNC deben usar .configureawait (Falso) para evitar puntos muertos ( Como se discutió aquí ), pero como estoy escribiendo una biblioteca que nunca tendrá que acceder a la UI. o webcontext, soy seguro para hacer eso.

    También notaré que la biblioteca de SQL típicamente también tiene funciones sincrónicas y de ASYNC que se pueden usar, por lo que si está haciendo el trabajo en la función SYNC, llamaría a su función de sincronización y, si está haciendo el trabajo en el ASYNC Función, llamaría a su función de ASYNC.

    Se aprecian los pensamientos / sugerencias.

    - Editar: También he publicado esta pregunta en los foros de MSDN aquí para intentar obtener una respuesta oficial de MS -

¿Fue útil?

Solución

Quiero tener funciones sincrónicas y asíncronas para cada operación, ya que esta biblioteca será utilizada por la consola y las aplicaciones de la 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:

Otros consejos

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

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

La devolución de llamada de AsignProjects es solo un delegado simple que lleva a la lista devuelta de proyectos:

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 Sync o Async.

Se crean tres clases: una base, una sincronización y una async:

 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 solicitud, puede decidir cómo desea cargar datos ... Esto podría inyectarse a través de un contenedor de IOC, pero se codifica con fines demo:

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

Ahora, su código de llamadas se ve igual y no es el más sabio para si es Async o Sync:

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

Utilizo esto regularmente para pruebas de unidad (sincronización), aplicaciones WPF (ASYNC) y aplicaciones de la consola (sincronización).

No parece haber un punto para simplemente marcar un método como Async sin usar un AWAIT. Lo marcando como ASYNC no lo hace asíncrono, le permite usar espera (el código ejecutado en la espera es lo que sucede de manera asíncrona, y luego el resto del método de ASYNC también se hará de forma asíncrona) en el cuerpo del método: < / p>

Típicamente, un método modificado por la palabra clave ASYNC contiene al menos una expresión o declaración. El método se ejecuta de forma síncrona hasta que alcance la primera expresión de espera, en qué punto se suspende hasta que se complete la tarea esperada. Mientras tanto, el control se devuelve a la persona que llama del método. Si el método no contiene una expresión o declaración de espera, entonces se ejecuta de forma sincrónica. Una advertencia de compilador le alerta a cualquier método de ASYNC que no contenga esperar porque esa situación puede indicar un error. Para obtener más información, consulte Compilador Advertencia CS4014.

de: async < / p>

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top