C#具有异步函数调用同步函数或同步函数调用异步函数

dea*_*dog 16 c# asynchronous synchronous async-await .net-4.5

我正在编写一个C#.Net 4.5库,用于执行常见的SQL数据库操作(备份,恢复,执行脚本等).我希望每个操作都有同步和异步函数,因为这个库将由控制台和GUI应用程序使用,但我不想在任何地方重复代码.所以我看到它,我有两个选择:

  1. 编写在同步函数中执行工作的代码,然后将其包装在async函数的任务中,如下所示:

    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);  
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 编写在异步函数中执行工作的代码,并使用.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.  
    }
    
    Run Code Online (Sandbox Code Playgroud)

一种选择比另一种更好吗?这是一个最佳实践吗?或者还有其他(更好的)替代方案吗?

我知道使用.Wait()的一个警告是async函数中的所有await语句都必须使用.ConfigureAwait(false)来避免死锁(如这里所讨论的),但是因为我正在编写一个永远不会存在的库需要访问UI或WebContext我可以安全地做到这一点.

我还要注意,SQL库通常也有可以使用的同步和异步函数,所以如果在同步函数中工作,我会调用它们的同步函数,如果在异步函数中工作,我会调用他们的异步功能.

赞赏的想法/建议.

- 编辑:我也在MSDN论坛上发布了这个问题,试图获得正式的MS回复 -

Ste*_*ary 12

我希望每个操作都有同步和异步函数,因为这个库将由控制台和GUI应用程序使用,但我不想在任何地方重复代码.

最好的答案是:不要.

Stephen Toub有两个关于这个主题的优秀博客文章:

他建议将异步方法公开为异步方法,将同步方法公开为同步方法.如果需要公开两者,则将常用功能封装在私有(同步)方法中,并复制异步/同步差异.