【问题标题】:UI still freezing when using async/await使用 async/await 时 UI 仍然冻结
【发布时间】:2013-10-08 16:53:46
【问题描述】:

我不是异步操作方面的专家,希望有人能帮我指出问题。

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

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 中,我这样调用方法,

int _recordsAffected = await MyClass.ExecuteNonQueryRawSQLAsync("INSERT....");

为了测试它是否真的有效,我尝试在连接字符串中提供一个无效的数据库服务器地址,以便它继续搜索直到它抛出异常。

当程序仍在连接时,UI 冻结。我的包装中缺少什么?还是我需要做任何其他需要的初始化?

【问题讨论】:

  • 你在里面调用ExecuteNonQueryRawSQLAsync的方法是async吗?
  • @ChrisMantle 这是我的包装器的名称。在包装器内部,是一个异步方法ExecuteNonQueryAsync()

标签: c# winforms asynchronous


【解决方案1】:

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

  • 使用 IP 地址而不是名称
  • 确保从工作线程启动Open* / Connect* / 任何 - 也许是Task.StartNew

未经测试,但推测:

await Task.StartNew(_conn.Open);

【讨论】:

  • 这个马克有任何文档吗?还是你凭经验发现的?
  • @SriramSakthivel 我没看过;基本上,我通过遇到一个非常相似的问题发现了这一点 - IIRC 然后我偷看了反射器
  • @Rossana:我之前的评论有一个指向我的博客的链接,我解释了为什么我不推荐StartNew。我建议您按照 Marc 建议的方式更改包装器,但使用 Run 而不是 Factory.StartNew
  • @Rossana:是的,我就是这个意思。
  • @Rossana:这与 Marc 在他的回答中描述的问题相同。总而言之,很多 .NET 网络调用实际上不是异步的。
【解决方案2】:

await "somemethod" 并不意味着该方法被异步调用。您仍在执行常规方法调用,该方法调用将像其他任何方法一样运行,直到被调用的方法决定返回一个表示异步操作的任务,然后您等待。

如果该方法在返回等待任务之前做了很多耗时的事情,您可以使用TaskFactory.Startnew() 调用它。

【讨论】:

  • 那么我的答案与这个有什么不同? stackoverflow.com/a/19029317/2816021
  • @Rossana 注意帖子说“正确编写的方法”。如果该方法在创建任务时阻塞,则它不是“正确编写的”。异步方法应该立即返回。如果创建任务很耗时(它需要解析 DNS 命名或其他内容),则应将创建本身包装在一个新任务中,以便客户端认为整个事情只是一个等待任务。
猜你喜欢
  • 2016-06-13
  • 2015-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多