在其阻塞版本中使用方法的异步实现
Use async implementation of a method in its blocking version
我创建了 Stream
的自定义子类,实现了 Read
。
虽然实现中使用的操作可以很好地利用 async
API,所以我也想提供一个 ReadAsync
实现。
这些方法有很多相似的行为,避免代码重复的最简单方法是将逻辑保留在 ReadAsync
实现中,并在 Read
实现中使用它。这看起来像这样:
public override int Read(byte[] buffer, int offset, int count)
{
return ReadAsync(buffer, offset, count).Result;
}
这种方法会有什么影响吗?由于 Read
方法应该在当前线程上阻塞,我认为它完全符合规范。
谢谢!
Would there be any implications with this approach?
是的,这就是 sync over async anti-pattern,应该避免。主要原因是很容易造成死锁.
怎么可能?当您阻塞线程时,您的内部 ReadAsync
可能正在等待异步操作完成。例如,如果此线程是 UI 消息循环线程,则它当前处于阻塞状态。当您的 await
完成时(假设您没有在内部使用 ConfigureAwait(false)
),它会在尝试将延续编组回它时出现死锁。
编写异步代码时,您会遇到一些代码重复,这是无法避免的。尝试尽可能多地重复使用。例如,如果两种代码方法在开头都有同步部分,您可以将其提取到异步和同步版本都将使用的第三种方法。
这取决于您的 Async 方法的实现 - 如果它等待当前线程进行某些操作,则会出现死锁。通常最好不要阻塞等待异步方法。
我创建了 Stream
的自定义子类,实现了 Read
。
虽然实现中使用的操作可以很好地利用 async
API,所以我也想提供一个 ReadAsync
实现。
这些方法有很多相似的行为,避免代码重复的最简单方法是将逻辑保留在 ReadAsync
实现中,并在 Read
实现中使用它。这看起来像这样:
public override int Read(byte[] buffer, int offset, int count)
{
return ReadAsync(buffer, offset, count).Result;
}
这种方法会有什么影响吗?由于 Read
方法应该在当前线程上阻塞,我认为它完全符合规范。
谢谢!
Would there be any implications with this approach?
是的,这就是 sync over async anti-pattern,应该避免。主要原因是很容易造成死锁.
怎么可能?当您阻塞线程时,您的内部 ReadAsync
可能正在等待异步操作完成。例如,如果此线程是 UI 消息循环线程,则它当前处于阻塞状态。当您的 await
完成时(假设您没有在内部使用 ConfigureAwait(false)
),它会在尝试将延续编组回它时出现死锁。
编写异步代码时,您会遇到一些代码重复,这是无法避免的。尝试尽可能多地重复使用。例如,如果两种代码方法在开头都有同步部分,您可以将其提取到异步和同步版本都将使用的第三种方法。
这取决于您的 Async 方法的实现 - 如果它等待当前线程进行某些操作,则会出现死锁。通常最好不要阻塞等待异步方法。