检测滥用Async / Await:阻止阻止呼叫

时间:2013-12-08 17:07:57

标签: c# .net async-await c#-5.0

我正在开发一个可扩展的游戏服务器系统,并试图为这个新项目过度使用await / async。到目前为止,我设法遇到了几个陷阱。我已经找到了大部分解决方案并开发了一种如何编写异步方法的“常见做法”,以便这些陷阱易于检测和解决。避免。不幸的是,以下令我头疼:

1)示例:

async Task<int> RunSqlQuery()
{
    DbCommand cmd = conn.CreateCommand();
    ...
    cmd.ExecuteReader();
    ...
}

WHOOOM!这是一个糟糕的原因有几个。一,有一个ExecuteReaderAsync(),可以解决这个问题。其次,此调用将阻止并停止内部异步框架的工作线程。在桌面环境中不是太关键,但不幸的是,如果你的服务器每秒有8000个请求,这会严重损害你的性能,并且很难找到引起问题的精确线路。

2)示例:

void ThisHurts()
{
    someTask.GetAwaiter().GetResult();
}

async Task<int> RunQuery()
{
    ...
    lock(something)
    {
        ThisHurts();
    }
    ...
}

我承认这个看起来有点工程来证明我的观点,但在处理大量代码时,这是一种难以避免的情况。基本上在锁定中等待等待是致命的。这是一个等待发生的灾难(字面上)。有很多解释为什么,不管它们是否相信,它们都是真的,构建类似于上面的东西,如果你的服务器上有负载并且大量的竞争条件开始链接在一起,你的代码几乎会立即死亡......

所以这个问题是关于如何检测等待的错误用法。有没有像Resharper这样的工具(它似乎不支持我想要的大部分内容)。我认为微软应该标记所有非阻塞方法并迫使人们以异步兼容方式包装它们,或者在尝试在异步方法中调用它们时发出编译器错误。此外,他们可能会强迫您使用新的“块”关键字在所有未标记为非阻塞的方法之前添加,以便您可以使用它们,但会立即显示耻辱。

到目前为止,我看到的异步框架的主要问题是误用只会在重负载下显示,这通常非常难以调试&amp;追踪,因为它有如此多的数据,你附加一个debuigger的那一刻问题就消失了,因为负载消失了。太棒了;)

1 个答案:

答案 0 :(得分:3)

工具仍围绕asyncawait开发。在这一点上(2013年底),我会说我们有一些可行的功能。在接下来的几年里,我确实期待更多。

编译器不适合添加此功能;它应该将C#转换为IL,而不是试图强制执行良好的编码实践。它确实可以作为C#语言的一部分进行“简单”检查(await内没有lock,控制台应用没有async void Main,等)。

编写自己的支票的可能性包括:StyleCop / FxCop / VS代码分析,NDepend的CQL,Re#插件等。

相关问题