【发布时间】:2012-07-25 07:43:00
【问题描述】:
我正在编写一个 C# .Net 4.5 库,用于执行常见的 sql 数据库操作(备份、恢复、执行脚本等)。我希望每个操作都有同步和异步功能,因为这个库将被控制台和 GUI 应用程序使用,但我不想到处重复代码。所以在我看来,我有两个选择:
-
编写在同步函数中完成工作的代码,然后将其包装在异步函数的任务中,如下所示:
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); } -
编写在异步函数中完成工作的代码,并使用 .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. }
一种选择比另一种更好吗?一个是最佳实践吗?或者还有其他(更好的)替代品吗?
我知道使用 .Wait() 的一个警告是异步函数中的所有等待语句都必须使用 .ConfigureAwait(false) 以避免死锁 (as discussed here),但是因为我正在编写一个库永远不需要访问 UI 或 WebContext 我可以安全地这样做。
我还要注意,SQL 库通常也有可以使用的同步和异步函数,所以如果在同步函数中工作,我会调用它们的同步函数,如果在异步中工作函数,我会调用他们的异步函数。
感谢您的想法/建议。
-- 编辑:我还发布了这个问题on the MSDN forums here 以尝试获得官方的 MS 回复--
【问题讨论】:
-
推荐的命名方式是异步方法以“Async”结尾。除此之外,这两种选择都不是更好。虽然,使用 ConfigureAwait(false) 确实限制了您的 api 的使用方式......
-
我通常会来一些已经写好的东西。如果那里根本不支持异步,那么我会做你的例子 1。
标签: c# asynchronous synchronous .net-4.5 async-await