【发布时间】:2019-06-14 21:09:44
【问题描述】:
我有以下代码从 TCP 流中读取字节(我已删除错误检查):
/// <summary>Awaitable. Reads a certain amount of bytes from a network stream. Returns false
/// on error</summary>
async Task<bool> readBytes (NetworkStream stream, byte []buffer, int totalBytes)
{
int bytesRead = 0;
while (true)
{
var br = await stream.ReadAsync (buffer, bytesRead, totalBytes - bytesRead);
if (br == 0) return false; // closed stream
bytesRead += br;
if (bytesRead >= totalBytes) return true;
}
}
然后我在外部使用它来接收4个字节的数据长度和数据主体(伪代码,我已经删除了错误检查和分配,只是为了提供一个想法):
success = await readBytes(stream, header, 4);
success = await readBytes(stream, data, dataLength);
presentDataToApp(data, dataLength);
客户端/服务器必须几乎实时交互(这是一个客户端应用程序调整多个参数的游戏,例如灯光)。例如,客户端有一个 WinForms 滑块,并将所有更改传输到服务器应用程序。移动该滑块时,一秒钟内可能会有很多更新(从我的日志来看,它每秒发送数据大约 100 次)。
只要服务器(运行我粘贴的代码)通过 Visual Studio 运行,此代码就可以很好地实时运行。但是,当我在没有 Visual Studio(或使用 Ctrl+F5)的情况下运行服务器应用程序时,通信开始严重滞后。
为了放弃异步/等待问题,我克隆了 comms 类并通过线程运行它,删除了所有异步/等待函数。该代码现在可以在 Visual Studio 和独立环境中实时运行(因此这是与 async/await 相关的问题)。
为什么在这种情况下 async/await 通信滞后? (一秒钟内肯定有很多等待)。什么决定了在没有准备好数据的等待之后等待的时间量? (我以为是计时器分辨率,但无论我如何执行服务器应用程序,它在我的系统上似乎都是 1 毫秒)。
【问题讨论】:
-
在发布模式下运行会发生什么?
-
async/await 不是一个孤立的问题。向我们展示您如何称呼它,以实现所有其他异步或线程。
-
我的第一个疯狂猜测 - 您的“发送”代码饿死了您的“接收”代码。你能检查一下,在没有 Visual Studio 的情况下每秒发送多少次?还可以尝试设置硬限制(比如每秒 50 次,因为我怀疑你需要更多),看看是否有帮助。
-
听起来你的窗口的消息循环可能已经饱和了,因为这就是实际上将延续带回 UI 线程的方式。
-
另外,一点旁注。您的计时器分辨率实际上不是 1 毫秒,Windows 不会为您提供比大约 13-14 毫秒更好的分辨率。
标签: c# asynchronous async-await