我还没有'得到'异步并等待,我正在寻找一些关于我即将解决的特定问题的澄清。基本上,我需要编写一些能够处理TCP连接的代码。它基本上只是接收数据并处理它,直到连接关闭。
我通常使用NetworkStream BeginRead和EndRead模式编写此代码,但由于async / await模式更清晰,我很想使用它。但是,由于我无法完全理解这些涉及到什么,我对后果有点警惕。一个人会比另一个人使用更多的资源;将使用一个线程,其他人将使用IOCP等。
令人费解的示例时间。这两个做同样的事情 - 计算流中的字节:
class StreamCount
{
private Stream str;
private int total = 0;
private byte[] buffer = new byte[1000];
public Task<int> CountBytes(Stream str)
{
this.str = str;
var tcs = new TaskCompletionSource<int>();
Action onComplete = () => tcs.SetResult(total);
str.BeginRead(this.buffer, 0, 1000, this.BeginReadCallback, onComplete);
return tcs.Task;
}
private void BeginReadCallback(IAsyncResult ar)
{
var bytesRead = str.EndRead(ar);
if (bytesRead == 0)
{
((Action)ar.AsyncState)();
}
else
{
total += bytesRead;
str.BeginRead(this.buffer, 0, 1000, this.BeginReadCallback, ar.AsyncState);
}
}
}
......而且......
public static async Task<int> CountBytes(Stream str)
{
var buffer = new byte[1000];
var total = 0;
while (true)
{
int bytesRead = await str.ReadAsync(buffer, 0, 1000);
if (bytesRead == 0)
{
break;
}
total += bytesRead;
}
return total;
}
在我看来,异步方式看起来更干净,但是我的未受过教育的大脑告诉我的'while(true)'循环会使用额外的线程,更多的资源,因此不会像另一个。但我很确定这是错的。这些是以同样的方式做同样的事吗?
答案 0 :(得分:8)
在我看来,异步的方式看起来更干净,但是有这样的同时(真实)&#39;我未受过教育的大脑告诉我的循环将使用额外的线程,更多的资源,因此不会像另一个那样扩展。
不,它不会。循环仅在实际运行代码时使用线程......就像在BeginRead
回调中一样。 await
表达式将控制返回到调用代码的任何位置,已经注册了一个延续,它继续跳回到方法中的正确位置(在适当的线程中,基于同步上下文),然后继续运行直到它到达方法的末尾或点击另一个await
表达式。它正是你想要的:))
值得进一步了解async / await如何在幕后工作 - 您可能希望从the MSDN page on it开始,作为跳跃点。