我不确定是否丢失了某些东西,或者SslStream(以及可能包装内部流的其他流类)中确实存在设计缺陷。
考虑以下伪代码:
MyStream
{
Task<int> ReadAsync()
{ ... }
}
...
{
MyStream my = new MyStream();
SslStream ssl = new SslStream(my);
ssl.ReadAsync(...);
}
尽管可以预期SslStream.ReadAsync最终会调用MyStream.ReadAsync,但不会。相反,它将调用MyStream.BeginRead(如果已定义)。如果未定义MyStream.BeginRead,则该行为将很难预测(它取决于MyStream源自哪个类,依此类推)。
简而言之,要使SslStream的异步/等待方法按预期工作,需要实现内部流类的BeginXXX / EndXXX(非异步/等待方法)。
BeginXXX / EndXXX模式的开发比异步/等待模式复杂得多(对我而言,这就是引入异步/等待的原因-使异步编程更容易)。但是仍然需要开发BeginXXX / EndXXX方法的要求无法达到异步/等待的目的。
此外,还需要了解SslStream类的内部实现(因为如果实现不同,它可以直接调用InnerStream.ReadAsync)。我的意思是SslStream的公共签名不能清楚地为我提供有关是否应在内部流类中实现ReadAsync或BeginRead的足够信息。
为此,我需要使用反复试验的方法或检查SslStream的源代码(以及它的Stream父级,因为SslStream继承了基本Stream类的ReadAsync)。这似乎不是一种可靠且直接的代码编写方法。
SslStream / Stream类中的异步/等待方法(如ReadAsync)的当前实现是否有原因?
最佳答案
Task
实现了IAsyncResult
,因此您应该可以摆脱
return ReadAsync(...);
作为
BeginRead
的实现。也许有点复杂,例如,您需要将回调连接为该任务的延续。但是您可以重用代码。顺便说一句,您违反了Stream API合同,因为
BeginRead
与ReadAsync
有所不同。严格来说,这是您的错,而不是框架问题。我的意思是SslStream的公共签名不能清楚地为我提供有关是否应在内部流类中实现ReadAsync或BeginRead的足够信息。
没必要知道。从类继承时,您将继承该类具有的所有义务。您必须实现所有内容,因为这是您对该类用户的承诺。明显的示例:如果从
IEnumerator
派生,则不仅可以实现MoveNext
,还可以省略Current
并期望调用者可以工作。关于c# - SslStream.ReadAsync永远不会调用InnerStream.ReadAsync,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30372241/