gpt4 book ai didi

c# - 什么决定了 "await"花费的时间?

转载 作者:行者123 更新时间:2023-11-30 22:54:07 24 4
gpt4 key购买 nike

我有以下代码从 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 slider ,并将所有更改传输到服务器应用程序。移动该 slider 时,一秒钟内可能会有很多更新(根据我的日志,它发送数据的速度约为 100 次/秒)。

只要服务器(运行我粘贴的代码)通过 Visual Studio 运行,此代码就可以实时运行。但是,当我在没有 Visual Studio(或使用 Ctrl+F5)的情况下运行服务器应用程序时,通信开始严重滞后。

为了排除异步/等待问题,我克隆了通信类并通过线程运行它,删除了所有异步/等待函数。代码现在可以在 Visual Studio 和独立版本中实时运行(因此这是一个与 async/await 相关的问题)。

在这种情况下,为什么 async/await 滞后通信? (一秒钟内肯定有很多等待)。什么决定了在没有准备好数据的等待之后等待的时间量? (我认为这是定时器分辨率,但无论我如何执行服务器应用程序,它在我的系统上似乎都是 1 毫秒)。

最佳答案

The client/server must interact in almost realtime

在您同时控制客户端和服务器的任何情况下,我总是推荐 SignalR。与原始套接字相比,针对 SignalR 进行编程要容易得多。

This code works well and in realtime, as long as the server is run through Visual Studio. However, when I run the server app without Visual Studio (or using Ctrl+F5) the communication starts lagging badly.

这太奇怪了。 VS 使您的代码运行更快?对此我没有任何解释。

What does determine the amount of time waited after an await that doesn't have the data ready takes?

这里发生的几件事都可能产生影响。

第一个是await捕获上下文并在该上下文中恢复。如果它是 UI 上下文,这尤其是一个问题。 At 100 updates per second, you're reaching the limit of what's practical .如果你的await s 正在 UI 线程上恢复,您可以使用 ConfigureAwait(false) 避免这种“性能因千次 Papercut 而死亡” .如果真的是await这是导致放缓的原因,请花时间查看 Zen of Async video .

第二个是有很多内存流失。 readBytes至少每个数据包都需要一个单独的数组(假设您重用 header 数组),并且还有许多 Task周围的实例。 如果分析表明问题是内存流失,那么consider using the new Memory<T> -based socket APIs that avoid the byte arrays, as well as the new ValueTask<T> -based APIs which avoid the Task allocations when the data is already arrived .例如,.NET Core 2.1 Stream原料药 ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken);如果分析表明问题是内存流失,但您还没有使用 .NET Core 2.1,那么您可以使用 SocketAsyncEventArgs APIs .

关于c# - 什么决定了 "await"花费的时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56596440/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com