c0D*_*g1c 5 .net c# async-await .net-4.5
我正在尝试将一些TcpClient相关代码移植到.net 4.5,使用StreamSocket和DataReader替代.
我有一个名为的函数ReadLine(),它在任何地方都使用.通过DataReader在LoadAsync()此代码的body()中使用,我的方法被强制用async关键字标记.
连锁反应如下:现在我有数百个地方需要添加async到调用方法并应用等待基础async方法调用.
这引出了我的下一个问题...是否有一种简单的方法来包装,ReadLine()以便调用方法不知道它是一个异步方法,所以我不必更改我的其余代码?
另外......我经常在一个循环中使用这个方法调用,来自多个地方.如果现在标记了这些方法async,我恐怕我可能会在不应该的时候从数据流中读取数据,这将导致各种恶梦.这是一个问题还是我想得太远了?
另外......我经常在一个循环中使用这个方法调用,来自多个地方.如果这些方法现在被标记为异步,我恐怕我不应该在流中读取数据,这将导致各种恶梦.这是一个问题还是我想得太远了?
如果你总是await在调用*Async方法时使用,那么你的async方法就像同步方法一样(除了它们不会阻塞).因此,await在循环中使用将像您期望的那样工作.
async确实通过代码库"增长".我通常认为这与关于"乌龟一直向下"的旧故事类似; 其他人称之为"僵尸病毒".
我在博客上详细描述了死锁情况.正如我所说,最好的选择是允许async增长.
如果必须为异步方法创建同步包装器,请参阅Stephen Toub的建议.你可以使用Task.Result,但你需要做两件事:
ConfigureAwait(false)到处使用.这将回避僵局局面.Result具有不同的错误处理语义.对于您的特定示例,这样的事情就足够了:
private async Task<string> ReadLineAsync()
{
... // *Every* await in this method and every method it calls
// must make use of ConfigureAwait(false).
}
public string ReadLine()
{
try
{
return ReadLineAsync().Result;
}
catch (AggregateException ex)
{
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
在选择混合同步/异步代码库之前,请仔细考虑复杂性.它并不像第一次出现那么容易.
PS一般来说,无论如何,TCP/IP代码都应该是异步的.在套接字上进行连续异步读取通常是个好主意.
| 归档时间: |
|
| 查看次数: |
2048 次 |
| 最近记录: |