将现有的C#同步方法转换为使用async/await实现异步方法?

4

从下面的同步I/O绑定方法开始,我如何使用async/await将其变为异步方法?

public int Iobound(SqlConnection conn, SqlTransaction tran)
{
    // this stored procedure takes a few seconds to complete
    SqlCommand cmd = new SqlCommand("MyIoboundStoredProc", conn, tran);
    cmd.CommandType = CommandType.StoredProcedure;

    SqlParameter returnValue = cmd.Parameters.Add("ReturnValue", SqlDbType.Int);
    returnValue.Direction = ParameterDirection.ReturnValue;
    cmd.ExecuteNonQuery();

    return (int)returnValue.Value;
}

MSDN的示例都假定已经存在一个*Async方法,并没有为I/O绑定操作自己创建该方法提供任何指导。

我可以使用Task.Run(),并在这个新的Task中执行Iobound()方法,但由于该操作不是CPU-bound,因此不建议创建新的Task。

我希望使用async/await,但我卡在了如何转换这个方法的基本问题上。


4
为什么不直接使用ExecuteNonQueryAsync() - Camilo Terevinto
2
请在你的 SqlCommand 上使用 using - slugster
在谷歌上搜索,实际上有很多关于如何装饰您的方法以成为await并使用Task<>的示例。 - MethodMan
@CamiloTerevinto,我可以问一下你为什么不断编辑我的答案格式吗?{的位置(是否换行)是个人偏好,更改它并没有增加任何价值。 - Evk
@Evk 如果阅读需要滚动而不是直接可视,那么这已经不仅仅是个人偏好的问题了。 - Camilo Terevinto
@CamiloTerevinto 但是对于我来说,即使在移动设备上(保持原始格式),它也适合我的横向空间而无需滚动。 - Evk
1个回答

7

这种方法的转换非常简单:

// change return type to Task<int>
public async Task<int> Iobound(SqlConnection conn, SqlTransaction tran) 
{
    // this stored procedure takes a few seconds to complete
    using (SqlCommand cmd = new SqlCommand("MyIoboundStoredProc", conn, tran)) 
    {
        cmd.CommandType = CommandType.StoredProcedure;
        SqlParameter returnValue = cmd.Parameters.Add("ReturnValue", SqlDbType.Int);
        returnValue.Direction = ParameterDirection.ReturnValue;
        // use async IO method and await it
        await cmd.ExecuteNonQueryAsync();
        return (int) returnValue.Value;
    }
}

@MikeZ 那么通常情况下,您实际上不需要将此方法设置为异步。异步是用于异步IO(正如您所知道的那样),而现在所有IO都有异步版本(文件、套接字、数据库、Web请求等)。如果您有反例,请提供一个。 - Evk
谢谢!但我应该选择一个不同的例子。在这种情况下,存在一个现有的Async方法ExecuteNonQueryAsync(),假设I/O绑定调用中没有现有的Async方法。如何将Iobound()转换为IoboundAsync()而不需要将同步代码包装在Task.Run()中,因为这对于I/O绑定代码来说并不推荐? - MikeZ
2
@MikeZ 我已经回答了。请提供一个没有异步版本的IO示例。如果你指的是你编写的另一个同步IO方法,那么你应该先将其转换为异步。因此,异步应该一直到底层。 - Evk
现在所有的IO都有异步版本了。嗯,我不知道这一点。也许这就是我缺少的部分。 - MikeZ
1
@MikeZ,你需要生成异步客户端代码。即使WCF服务在服务器上是同步的,客户端也可以选择异步调用它(在客户端)。请参见此处:https://learn.microsoft.com/en-us/dotnet/framework/wcf/synchronous-and-asynchronous-operations。因此,你的目标是创建/生成Channel.MethodAsync(),当然不需要任何Task.Run。 - Evk
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接