我不确定是我漏掉了什么还是SslStream(以及可能包装内部流的其他流类)确实存在设计缺陷。
尽管人们可能期望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)的当前实现是否有原因?
考虑以下伪代码:
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)的当前实现是否有原因?
CancellationToken.None
给 continuation 安全吗?我总是对这样的东西有点模糊... 如果task
有一个CancellationToken
,取消它会阻止 continuation,对吧?这可能会引起一些问题(微小?)。哦,我喜欢使用GetAwaiter
的技巧:D 它是否正确地保留了原始调用堆栈? - Luaan