C# 使用async/await时UI仍然冻结

C# 使用async/await时UI仍然冻结,c#,winforms,asynchronous,C#,Winforms,Asynchronous,我不是非同步操作方面的专家,希望有人能帮我指出问题所在 在我的一个方法中,我编写了一个包装器 public static async Task<int> ExecuteNonQueryRawSQLAsync(string sqlStatement) { int _returnValue = -1; using (SqlConnection _conn = new SqlConnection("connectionString")) { usin

我不是非同步操作方面的专家,希望有人能帮我指出问题所在

在我的一个方法中,我编写了一个包装器

public static async Task<int> ExecuteNonQueryRawSQLAsync(string sqlStatement)
{
    int _returnValue = -1;
    using (SqlConnection _conn = new SqlConnection("connectionString"))
    {
        using (SqlCommand _comm = new SqlCommand())
        {
            _comm.Connection = _conn;
            _comm.CommandText = sqlStatement;
            _comm.CommandType = CommandType.Text;

            // other codes on setting parameter

            try
            {
                await _conn.OpenAsync();
                _returnValue = Convert.ToInt32(await _comm.ExecuteNonQueryAsync());
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
    return _returnValue;
}
为了测试它是否真的工作,我尝试在连接字符串中提供一个无效的数据库服务器地址,以便它继续搜索,直到抛出异常为止


当程序仍在连接时,UI冻结。我的包装里少了什么?或者我还需要进行任何其他必要的初始化吗?

从苦涩的记忆中,TCP套接字有一个非常类似的问题-基本上,名称解析是同步执行的,即使是异步操作。有两种解决方法:

  • 使用IP地址而不是名称
  • 确保从工作线程启动
    打开*
    /
    连接*
    /任何任务-可能是
    任务。开始新建
未经测试,但推测:

await Task.StartNew(_conn.Open);
wait“somemethod”并不意味着该方法被异步调用。您仍在执行常规方法调用,该调用将像其他方法一样运行,直到被调用的方法决定返回表示异步操作的任务,然后等待


如果该方法在返回等待的任务之前做了大量耗时的工作,那么可以使用调用它。

在中调用
ExecuteNonQueryRawSQLAsync
的方法是
async
?@ChrisMantle它是我的包装器的名称。在包装器中,有一个异步方法
ExecuteNonQueryAsync()
。有关于这个marc的文档吗?还是你凭经验发现的?@SriramSakthivel我还没看过;基本上,我发现这很难,因为我碰到了一个非常类似的问题——IIRC,然后我偷看了一下reflector@Rossana:我之前的评论有一个到我博客的链接,我在这里解释了为什么我不推荐
StartNew
。我建议您按照Marc建议的方式更改包装器,但使用
Run
而不是
Factory。StartNew
@Rossana:是的,这就是我的意思。@Rossana:这与Marc在回答中描述的问题相同。总而言之,很多.NET网络调用实际上都不是异步的。那么,我的回答与这个有什么不同呢@Rossana注意到帖子上说的是“正确编写的方法”。如果该方法在创建任务时阻塞,则说明该方法未“正确写入”。异步方法应该立即返回。如果任务的创建非常耗时(它需要解析DNS命名或其他什么),那么创建本身应该包装在一个新任务中,以便客户端将整个任务视为一个可等待的任务。
await Task.StartNew(_conn.Open);